1/** 2 * Naviga Gallery Slider 3 * Targets .gallery-slider > .gallery-image-slider markup. 4 * Builds an inline prev/next slider with #900 arrows, counter, caption and byline. 5 */ 6(function () { 7 'use strict'; 8 9 function buildSlider(wrapper) { 10 var slides = Array.prototype.slice.call(wrapper.querySelectorAll('.gallery-image-slider')); 11 if (slides.length < 1) return; 12 13 // Collect slide data from existing DOM 14 var items = slides.map(function (slide) { 15 var img = slide.querySelector('img.gallery_image'); 16 var caption = slide.querySelector('.bottom-container .caption'); 17 var byline = slide.querySelector('.bottom-container .byline'); 18 return { 19 src: img ? img.src : '', 20 alt: img ? (img.alt || '') : '', 21 caption: caption ? caption.textContent.trim() : '', 22 byline: byline ? byline.textContent.trim() : '' 23 }; 24 }); 25 26 var total = items.length; 27 var current = 0; 28 29 // ââ Build slider DOM ââââââââââââââââââââââââââââââââââââââââââââââ 30 31 var slider = document.createElement('div'); 32 slider.className = 'naviga-slider'; 33 34 // Image track 35 var track = document.createElement('div'); 36 track.className = 'naviga-slider-track'; 37 38 var mainImg = document.createElement('img'); 39 mainImg.className = 'naviga-slider-img'; 40 mainImg.decoding = 'async'; 41 mainImg.loading = 'eager'; 42 track.appendChild(mainImg); 43 44 slider.appendChild(track); 45 46 // Controls bar (prev | counter | next) 47 var controls = document.createElement('div'); 48 controls.className = 'naviga-slider-controls'; 49 50 function makeArrow(dir) { 51 var btn = document.createElement('button'); 52 btn.type = 'button'; 53 btn.className = 'naviga-slider-arrow naviga-slider-arrow--' + dir; 54 btn.setAttribute('aria-label', dir === 'prev' ? 'Previous image' : 'Next image'); 55 btn.innerHTML = dir === 'prev' 56 ? '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>' 57 : '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>'; 58 return btn; 59 } 60 61 var prevBtn = makeArrow('prev'); 62 var counter = document.createElement('span'); 63 counter.className = 'naviga-slider-counter'; 64 var nextBtn = makeArrow('next'); 65 66 controls.appendChild(prevBtn); 67 controls.appendChild(counter); 68 controls.appendChild(nextBtn); 69 slider.appendChild(controls); 70 71 // Caption / byline bar 72 var captionBar = document.createElement('div'); 73 captionBar.className = 'naviga-slider-caption-bar'; 74 75 var captionEl = document.createElement('p'); 76 captionEl.className = 'naviga-slider-caption'; 77 78 var bylineEl = document.createElement('p'); 79 bylineEl.className = 'naviga-slider-byline'; 80 81 captionBar.appendChild(captionEl); 82 captionBar.appendChild(bylineEl); 83 slider.appendChild(captionBar); 84 85 // ââ Update function âââââââââââââââââââââââââââââââââââââââââââââââ 86 87 function goTo(index) { 88 current = (index + total) % total; 89 var item = items[current]; 90 91 mainImg.src = item.src; 92 mainImg.alt = item.alt; 93 94 counter.textContent = (current + 1) + ' / ' + total; 95 96 captionEl.textContent = item.caption; 97 captionEl.style.display = item.caption ? '' : 'none'; 98 99 bylineEl.textContent = item.byline; 100 bylineEl.style.display = item.byline ? '' : 'none'; 101 102 captionBar.style.display = (item.caption || item.byline) ? '' : 'none'; 103 104 // Disable arrows at ends (non-looping feel) - keep clickable for looping 105 prevBtn.disabled = false;
106 nextBtn.disabled = false; 107 } 108 109 prevBtn.addEventListener('click', function () { goTo(current - 1); }); 110 nextBtn.addEventListener('click', function () { goTo(current + 1); }); 111 112 // Touch / swipe 113 var touchStartX = null; 114 track.addEventListener('touchstart', function (e) { 115 touchStartX = e.touches[0].clientX; 116 }, { passive: true }); 117 track.addEventListener('touchend', function (e) { 118 if (touchStartX === null) return; 119 var delta = e.changedTouches[0].clientX - touchStartX; 120 if (Math.abs(delta) > 40) { 121 delta < 0 ? goTo(current + 1) : goTo(current - 1); 122 } 123 touchStartX = null; 124 }, { passive: true }); 125 126 // Keyboard support when slider is focused 127 slider.setAttribute('tabindex', '0'); 128 slider.addEventListener('keydown', function (e) { 129 if (e.key === 'ArrowLeft') goTo(current - 1); 130 if (e.key === 'ArrowRight') goTo(current + 1); 131 }); 132 133 // Init first slide 134 goTo(0); 135 136 // Replace wrapper contents with the built slider 137 wrapper.innerHTML = ''; 138 wrapper.appendChild(slider); 139 } 140 141 function init() { 142 var galleries = document.querySelectorAll('.gallery-slider'); 143 Array.prototype.forEach.call(galleries, buildSlider); 144 } 145 146 if (document.readyState === 'loading') { 147 document.addEventListener('DOMContentLoaded', init); 148 } else { 149 init(); 150 } 151}());
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.