PageSourceSearch

https://www.mromagazine.com/wp-content/themes/kadence-pubx/js/pubx-secondary-nav-scroll.js?ver=1788103750

js mromagazine.com collected 2026-10-03 19:36:43 UTC 3,331 bytes, 115 lines download raw bytes

1/**
2 * Secondary nav horizontal controls.
3 * Adds left/right arrow buttons to .secondary-nav and scrolls menu track.
4 */
5(function () {
6	'use strict';
7
8	function getTrack(root) {
9		return root.querySelector('.menu-container') || root.querySelector('ul.kb-navigation.menu');
10	}
11
12	function updateState(root, track, prevBtn, nextBtn) {
13		var maxScrollLeft = Math.max(0, track.scrollWidth - track.clientWidth);
14		var scrollLeft = track.scrollLeft;
15		var nearStart = scrollLeft <= 2;
16		var nearEnd = scrollLeft >= maxScrollLeft - 2;
17		var hasOverflow = maxScrollLeft > 2;
18
19		root.classList.toggle('has-overflow', hasOverflow);
20		root.classList.toggle('show-left-fade', hasOverflow && !nearStart);
21		root.classList.toggle('show-right-fade', hasOverflow && !nearEnd);
22		root.classList.toggle('hide-left-arrow', !hasOverflow || nearStart);
23		root.classList.toggle('hide-right-arrow', !hasOverflow || nearEnd);
24
25		prevBtn.disabled = !hasOverflow || nearStart;
26		nextBtn.disabled = !hasOverflow || nearEnd;
27	}
28
29	function createButton(direction) {
30		var button = document.createElement('button');
31		button.type = 'button';
32		button.className = 'pubx-secondary-nav-control is-' + direction;
33		button.setAttribute('aria-label', direction === 'prev' ? 'Scroll secondary menu left' : 'Scroll secondary menu right');
34		return button;
35	}
36
37	function initSecondaryNav(root) {
38		if (!root || root.dataset.pubxSecondaryNavReady === '1') {
39			return;
40		}
41
42		var track = getTrack(root);
43		if (!track) {
44			return;
45		}
46
47		var prevBtn = createButton('prev');
48		var nextBtn = createButton('next');
49		var stepPx = 100;
50		var initialResetDone = false;
51
52		function scrollByStep(dir) {
53			root.classList.add('has-interacted');
54			var maxScrollLeft = Math.max(0, track.scrollWidth - track.clientWidth);
55			var amount = stepPx * dir;
56			var targetLeft = Math.max(0, Math.min(maxScrollLeft, track.scrollLeft + amount));
57			track.scrollTo({ left: targetLeft, behavior: 'smooth' });
58		}
59
60		prevBtn.addEventListener('click', function () {
61			scrollByStep(-1);
62		});
63
64		nextBtn.addEventListener('click', function () {
65			scrollByStep(1);
66		});
67
68		track.addEventListener('scroll', function () {
69			if (track.scrollLeft > 2) {
70				root.classList.add('has-interacted');
71			}
72			updateState(root, track, prevBtn, nextBtn);
73		});
74
75		track.addEventListener('wheel', function () {
76			root.classList.add('has-interacted');
77		}, { passive: true });
78
79		track.addEventListener('touchstart', function () {
80			root.classList.add('has-interacted');
81		}, { passive: true });
82
83		track.addEventListener('pointerdown', function () {
84			root.classList.add('has-interacted');
85		});
86
87		window.addEventListener('resize', function () {
88			updateState(root, track, prevBtn, nextBtn);
89		});
90
91		root.appendChild(prevBtn);
92		root.appendChild(nextBtn);
93		root.dataset.pubxSecondaryNavReady = '1';
94
95		// Force a stable initial left start so first menu items are reachable.
96		requestAnimationFrame(function () {
97			if (!initialResetDone) {
98				track.scrollLeft = 0;
99				initialResetDone = true;
100			}
101			updateState(root, track, prevBtn, nextBtn);
102		});
103	}
104
105	function init() {
106		var navs = document.querySelectorAll('.secondary-nav');
107		navs.forEach(initSecondaryNav);
108	}
109
110	if (document.readyState === 'loading') {
111		document.addEventListener('DOMContentLoaded', init);
112	} else {
113		init();
114	}
115})();

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.