1/** 2 * Authors Box â Frontend JavaScript 3 * Handles smooth scrolling and navigation arrow states for horizontal layout. 4 */ 5document.addEventListener('DOMContentLoaded', function () { 6 'use strict'; 7 8 function initHorizontalSliders() { 9 var wrappers = document.querySelectorAll('.ab-authors-wrapper.ab-layout-horizontal'); 10 if (!wrappers.length) return; 11 12 wrappers.forEach(function (wrapper) { 13 var track = wrapper.querySelector('.ab-authors-track'); 14 var prevBtn = wrapper.querySelector('.ab-scroll-arrow--prev'); 15 var nextBtn = wrapper.querySelector('.ab-scroll-arrow--next'); 16 17 if (!track || !prevBtn || !nextBtn) return; 18 19 function getScrollStep() { 20 // Scroll roughly 2 cards width or 60% of visible container width 21 return Math.max(180, Math.floor(track.clientWidth * 0.65)); 22 } 23 24 function updateArrowStates() { 25 // On mobile screens (<= 768px), arrows are hidden via CSS 26 if (window.innerWidth <= 768) return; 27 28 var maxScrollLeft = track.scrollWidth - track.clientWidth; 29 30 // If track does not overflow, hide or disable both arrows 31 if (maxScrollLeft <= 2) { 32 prevBtn.classList.add('is-disabled'); 33 nextBtn.classList.add('is-disabled'); 34 prevBtn.setAttribute('aria-disabled', 'true'); 35 nextBtn.setAttribute('aria-disabled', 'true'); 36 wrapper.classList.add('ab-no-overflow'); 37 return; 38 } 39 40 wrapper.classList.remove('ab-no-overflow'); 41 42 // Left arrow state 43 if (track.scrollLeft <= 4) { 44 prevBtn.classList.add('is-disabled'); 45 prevBtn.setAttribute('aria-disabled', 'true'); 46 } else { 47 prevBtn.classList.remove('is-disabled'); 48 prevBtn.setAttribute('aria-disabled', 'false'); 49 } 50 51 // Right arrow state 52 if (track.scrollLeft >= maxScrollLeft - 4) { 53 nextBtn.classList.add('is-disabled'); 54 nextBtn.setAttribute('aria-disabled', 'true'); 55 } else { 56 nextBtn.classList.remove('is-disabled'); 57 nextBtn.setAttribute('aria-disabled', 'false'); 58 } 59 } 60 61 // Scroll left button 62 prevBtn.addEventListener('click', function (e) { 63 e.preventDefault(); 64 if (prevBtn.classList.contains('is-disabled')) return; 65 var step = getScrollStep(); 66 track.scrollBy({ left: -step, behavior: 'smooth' }); 67 }); 68 69 // Scroll right button 70 nextBtn.addEventListener('click', function (e) { 71 e.preventDefault(); 72 if (nextBtn.classList.contains('is-disabled')) return; 73 var step = getScrollStep(); 74 track.scrollBy({ left: step, behavior: 'smooth' }); 75 }); 76 77 // Listen for scroll on the track 78 var scrollTicking = false; 79 track.addEventListener('scroll', function () { 80 if (!scrollTicking) { 81 window.requestAnimationFrame(function () { 82 updateArrowStates(); 83 scrollTicking = false; 84 }); 85 scrollTicking = true; 86 } 87 }, { passive: true }); 88 89 // Initial check 90 updateArrowStates(); 91 92 // Window resize listener 93 window.addEventListener('resize', function () { 94 updateArrowStates(); 95 }, { passive: true }); 96 97 // Recheck after images load 98 var images = track.querySelectorAll('img'); 99 images.forEach(function (img) { 100 if (!img.complete) { 101 img.addEventListener('load', updateArrowStates); 102 } 103 }); 104 }); 105 } 106 107 initHorizontalSliders(); 108});
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.