1(function () { 2 'use strict'; 3 4 document.querySelectorAll('.ritzau-block-feature-slider').forEach(function (block) { 5 var wrapper = block.querySelector('.ritzau-block-feature-slider__wrapper'); 6 var track = block.querySelector('.ritzau-block-feature-slider__track'); 7 var prevBtn = block.querySelector('.ritzau-block-feature-slider__prev'); 8 var nextBtn = block.querySelector('.ritzau-block-feature-slider__next'); 9 10 if (!track || !wrapper) { return; } 11 12 var realItems = Array.from(track.querySelectorAll('.ritzau-block-feature-slider__item')); 13 var count = realItems.length; 14 15 if (count === 0) { return; } 16 if (count === 1) { 17 realItems[0].classList.add('is-active'); 18 if (prevBtn) { prevBtn.style.display = 'none'; } 19 if (nextBtn) { nextBtn.style.display = 'none'; } 20 return; 21 } 22 23 // ââ Clone 2 items on each end so the 3-col view never shows a gap â 24 // DOM after cloning: 25 // [prevLastClone(0), lastClone(1), item0(2), ..., item(N-1)(N+1), firstClone(N+2), nextFirstClone(N+3)] 26 var prevLastClone = realItems[count - 2].cloneNode(true); 27 var lastClone = realItems[count - 1].cloneNode(true); 28 var firstClone = realItems[0].cloneNode(true); 29 var nextFirstClone = realItems[1].cloneNode(true); 30 31 [prevLastClone, lastClone, firstClone, nextFirstClone].forEach(function (c) { 32 c.setAttribute('aria-hidden', 'true'); 33 }); 34 35 track.insertBefore(lastClone, realItems[0]); 36 track.insertBefore(prevLastClone, lastClone); 37 track.appendChild(firstClone); 38 track.appendChild(nextFirstClone); 39 40 // Real items occupy indices 2 ⦠count+1. 41 // Start at index 3 (item1) so slide 1 is left, slide 2 is active center. 42 var curr = 3; 43 var isAnimating = false; 44 45 function getCols() { 46 return window.innerWidth >= 1024 ? 3 : 1; 47 } 48 49 function getItemWidth() { 50 return wrapper.offsetWidth / getCols(); 51 } 52 53 function getAllItems() { 54 return Array.from(track.querySelectorAll('.ritzau-block-feature-slider__item')); 55 } 56 57 function setItemWidths() { 58 var w = getItemWidth();
59 getAllItems().forEach(function (item) { 60 item.style.flexBasis = w + 'px'; 61 item.style.width = w + 'px'; 62 }); 63 } 64 65 function getTranslate(index) { 66 var cols = getCols(); 67 var itemWidth = getItemWidth(); 68 var centerOffset = cols === 3 ? 1 : 0; 69 return -(index - centerOffset) * itemWidth; 70 } 71 72 function setPosition(index, animate) { 73 track.style.transition = animate ? 'transform 0.4s ease' : 'none'; 74 track.style.transform = 'translateX(' + getTranslate(index) + 'px)'; 75 } 76 77 function updateActive() { 78 getAllItems().forEach(function (item, i) { 79 item.classList.toggle('is-active', i === curr); 80 }); 81 } 82 83 // ââ Initialise ââââââââââââââââââââââââââââââââââââââââââââââââââââ 84 setItemWidths(); 85 setPosition(curr, false); 86 updateActive(); 87 88 // ââ Navigation ââââââââââââââââââââââââââââââââââââââââââââââââââââ 89 function goNext() { 90 if (isAnimating) { return; } 91 isAnimating = true; 92 curr++; 93 setPosition(curr, true); 94 updateActive(); 95 } 96 97 function goPrev() { 98 if (isAnimating) { return; } 99 isAnimating = true; 100 curr--; 101 setPosition(curr, true); 102 updateActive(); 103 } 104 105 // Instant jump without CSS transition on items (prevents opacity/scale blink) 106 function instantJump(newCurr) { 107 block.classList.add('is-jumping'); 108 curr = newCurr; 109 setPosition(curr, false); 110 updateActive(); 111 requestAnimationFrame(function () { 112 requestAnimationFrame(function () { 113 block.classList.remove('is-jumping'); 114 }); 115 }); 116 } 117 118 // After transition, jump from clone zone back to real items 119 track.addEventListener('transitionend', function () { 120 isAnimating = false; 121 if (curr === count + 2) { 122 instantJump(2); 123 } else if (curr === 1) { 124 instantJump(count + 1); 125 } 126 }); 127 128 if (prevBtn) { prevBtn.addEventListener('click', goPrev); } 129 if (nextBtn) { nextBtn.addEventListener('click', goNext); } 130 131 // ââ Touch / swipe ââââââââââââââââââââââââââââââââââââââââââââââââââ 132 var touchStartX = 0; 133 wrapper.addEventListener('touchstart', function (e) { 134 touchStartX = e.touches[0].clientX; 135 }, { passive: true }); 136 137 wrapper.addEventListener('touchend', function (e) { 138 var diff = touchStartX - e.changedTouches[0].clientX; 139 if (Math.abs(diff) > 50) { 140 diff > 0 ? goNext() : goPrev(); 141 } 142 }, { passive: true }); 143 144 // ââ Recalculate on resize ââââââââââââââââââââââââââââââââââââââââââ 145 var resizeTimer; 146 window.addEventListener('resize', function () { 147 clearTimeout(resizeTimer); 148 resizeTimer = setTimeout(function () { 149 setItemWidths(); 150 setPosition(curr, false); 151 }, 100); 152 }); 153 }); 154})();
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.