1/** 2 * Gallery Carousel â gallery-carousel.js 3 * Vanilla JS. No dependencies. Supports keyboard, touch, and multiple 4 * independent carousels on the same page. 5 */ 6( function () { 7 'use strict'; 8 9 /** 10 * Initialise a single carousel wrapper element. 11 * 12 * @param {HTMLElement} wrapper 13 */ 14 function initCarousel( wrapper ) { 15 var track = wrapper.querySelector( '.gc-track' ); 16 var slides = wrapper.querySelectorAll( '.gc-slide' ); 17 var dots = wrapper.querySelectorAll( '.gc-dot' ); 18 var btnPrev = wrapper.querySelector( '.gc-btn--prev' ); 19 var btnNext = wrapper.querySelector( '.gc-btn--next' ); 20 21 if ( ! track || slides.length < 2 ) { 22 return; 23 } 24 25 var current = 0; 26 var total = slides.length; 27 var startX = null; 28 var isDragging = false; 29 30 /** 31 * Move to a specific slide index. 32 * 33 * @param {number} index 34 */ 35 function goTo( index ) { 36 // Clamp with wrap-around. 37 if ( index < 0 ) { 38 index = total - 1; 39 } else if ( index >= total ) { 40 index = 0; 41 } 42 43 // Update the track position. 44 track.style.transform = 'translateX(-' + ( index * 100 ) + '%)'; 45 46 // Update aria and class on slides. 47 slides[ current ].classList.remove( 'gc-slide--active' ); 48 slides[ current ].setAttribute( 'aria-hidden', 'true' ); 49 50 slides[ index ].classList.add( 'gc-slide--active' ); 51 slides[ index ].setAttribute( 'aria-hidden', 'false' ); 52 53 // Update dots. 54 if ( dots.length ) { 55 dots[ current ].classList.remove( 'gc-dot--active' ); 56 dots[ current ].setAttribute( 'aria-selected', 'false' ); 57 dots[ index ].classList.add( 'gc-dot--active' ); 58 dots[ index ].setAttribute( 'aria-selected', 'true' ); 59 } 60 61 current = index; 62 } 63 64 // Prev / Next buttons. 65 if ( btnPrev ) { 66 btnPrev.addEventListener( 'click', function () { 67 goTo( current - 1 ); 68 } ); 69 } 70 71 if ( btnNext ) { 72 btnNext.addEventListener( 'click', function () { 73 goTo( current + 1 ); 74 } ); 75 } 76 77 // Dot clicks. 78 dots.forEach( function ( dot ) { 79 dot.addEventListener( 'click', function () { 80 goTo( parseInt( dot.getAttribute( 'data-index' ), 10 ) ); 81 } ); 82 } ); 83 84 // Keyboard navigation when the wrapper or any child has focus. 85 wrapper.addEventListener( 'keydown', function ( e ) { 86 if ( e.key === 'ArrowLeft' ) { 87 e.preventDefault(); 88 goTo( current - 1 ); 89 } else if ( e.key === 'ArrowRight' ) { 90 e.preventDefault(); 91 goTo( current + 1 ); 92 } 93 } ); 94 95 // Touch / pointer swipe support. 96 wrapper.addEventListener( 'touchstart', function ( e ) { 97 startX = e.touches[ 0 ].clientX; 98 }, { passive: true } ); 99 100 wrapper.addEventListener( 'touchend', function ( e ) { 101 if ( startX === null ) { 102 return; 103 } 104 var deltaX = e.changedTouches[ 0 ].clientX - startX; 105 if ( Math.abs( deltaX ) > 40 ) { 106 goTo( deltaX < 0 ? current + 1 : current - 1 ); 107 } 108 startX = null; 109 } ); 110 111 // Mouse drag support (desktop). 112 wrapper.addEventListener( 'mousedown', function ( e ) { 113 startX = e.clientX; 114 isDragging = true; 115 } ); 116 117 document.addEventListener( 'mouseup', function ( e ) { 118 if ( ! isDragging ) { 119 return; 120 } 121 isDragging = false; 122 var deltaX = e.clientX - startX; 123 if ( Math.abs( deltaX ) > 40 ) { 124 goTo( deltaX < 0 ? current + 1 : current - 1 ); 125 } 126 startX = null; 127 } ); 128 129 // Make the wrapper focusable so keyboard events fire. 130 if ( ! wrapper.getAttribute( 'tabindex' ) ) { 131 wrapper.setAttribute( 'tabindex', '0' ); 132 } 133 } 134 135 /** 136 * Boot all carousels on the page once the DOM is ready. 137 */
138 function init() { 139 document.querySelectorAll( '.gc-carousel-wrapper' ).forEach( initCarousel ); 140 } 141 142 if ( document.readyState === 'loading' ) { 143 document.addEventListener( 'DOMContentLoaded', init ); 144 } else { 145 init(); 146 } 147 148} )();
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.