1function isImageLink(url) { 2 return /\.(jpg|jpeg|png|gif)$/i.test(url); 3} 4 5document.addEventListener("DOMContentLoaded", () => { 6 const lightbox = document.createElement("div"); 7 lightbox.id = "lightbox"; 8 document.body.appendChild(lightbox); 9 10 let touchStartX = 0; 11 let touchEndX = 0; 12 13 document.querySelectorAll('a:not(.no-lightbox)').forEach(el => { 14 const url = el.getAttribute('href'); 15 if (url && isImageLink(url)) { 16 el.classList.add('lightbox-image'); 17 el.setAttribute('title', url.split('/').pop().split('.')[0]); 18 } 19 }); 20 21 lightbox.addEventListener("click", event => { 22 if (!['next', 'prev'].includes(event.target.id)) { 23 lightbox.innerHTML = ''; 24 lightbox.classList.remove('open'); 25 document.body.style.overflow = ''; 26 } 27 }); 28 29 document.querySelectorAll('a.lightbox-image').forEach(el => { 30 el.addEventListener("click", event => { 31 event.preventDefault(); 32 lightbox.innerHTML = ` 33 <a id="close"></a> 34 <a id="next">›</a> 35 <a id="prev">‹</a> 36 <div class="img" style="background: url('${el.href}') center / contain no-repeat;"> 37 <img src="${el.href}" alt="${el.title}" /> 38 </div>`; 39 lightbox.classList.add('open'); 40 document.body.style.overflow = 'hidden'; 41 setGallery(el); 42 }); 43 }); 44 45 document.querySelectorAll('.image-gallery a.lightbox-image').forEach(el => el.classList.add('gallery')); 46 47 window.addEventListener('keydown', event => { 48 if (['ArrowLeft', 'ArrowRight', 'Escape'].includes(event.key)) { 49 document.getElementById(event.key === 'ArrowLeft' ? 'prev' : event.key === 'ArrowRight' ? 'next' : 'close')?.click(); 50 } 51 }); 52 53 lightbox.addEventListener('touchstart', event => { 54 touchStartX = event.touches[0].clientX; 55 }); 56 57 lightbox.addEventListener('touchend', event => { 58 touchEndX = event.changedTouches[0].clientX; 59 handleSwipe(); 60 }); 61 62 function handleSwipe() { 63 if (touchStartX - touchEndX > 50) { 64 document.getElementById('next')?.click(); 65 } else if (touchEndX - touchStartX > 50) { 66 document.getElementById('prev')?.click(); 67 } 68 } 69 70 lightbox.addEventListener('wheel', event => { 71 event.preventDefault(); 72 if (event.deltaY > 0) { 73 document.getElementById('next')?.click(); 74 } else if (event.deltaY < 0) { 75 document.getElementById('prev')?.click(); 76 } 77 }); 78}); 79 80function setGallery(el) { 81 const galleryElements = [...document.querySelectorAll('a.lightbox-image.gallery')]; 82 galleryElements.forEach(e => e.classList.remove('current')); 83 el.classList.add('current'); 84 85 if (galleryElements.length > 1) { 86 document.getElementById('lightbox').classList.add('gallery'); 87 } 88 89 const currentIndex = galleryElements.indexOf(el); 90 const prevIndex = (currentIndex - 1 + galleryElements.length) % galleryElements.length; 91 const nextIndex = (currentIndex + 1) % galleryElements.length; 92 93 document.getElementById('next').onclick = () => galleryElements[nextIndex].click(); 94 document.getElementById('prev').onclick = () => galleryElements[prevIndex].click(); 95}
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.