1// File#: _3_lightbox 2// Usage: codyhouse.co/license 3 4(function() { 5 var Lightbox = function(element) { 6 this.element = element; 7 this.id = this.element.getAttribute('id'); 8 this.slideshow = this.element.getElementsByClassName('js-lightbox__body')[0]; 9 this.slides = this.slideshow.getElementsByClassName('js-slideshow__item'); 10 this.thumbWrapper = this.element.getElementsByClassName('js-lightbox_thumb-list'); 11 lazyLoadLightbox(this); 12 initSlideshow(this); 13 initThumbPreview(this); 14 initThumbEvents(this); 15 } 16 17 function lazyLoadLightbox(modal) { 18 // add no-transition class to lightbox - used to select the first visible slide 19 Util.addClass(modal.element, 'lightbox--no-transition'); 20 //load first slide media when modal is open 21 modal.element.addEventListener('modalIsOpen', function(event){ 22 setSelectedItem(modal, event); 23 var selectedSlide = modal.slideshow.getElementsByClassName('slideshow__item--selected'); 24 modal.selectedSlide = Util.getIndexInArray(modal.slides, selectedSlide[0]); 25 if(selectedSlide.length > 0) { 26 if(modal.slideshowObj) modal.slideshowObj.selectedSlide = modal.selectedSlide; 27 lazyLoadSlide(modal); 28 resetVideos(modal, false); 29 resetIframes(modal, false); 30 updateThumb(modal); 31 } 32 Util.removeClass(modal.element, 'lightbox--no-transition'); 33 }); 34 modal.element.addEventListener('modalIsClose', function(event){ // add no-transition class 35 Util.addClass(modal.element, 'lightbox--no-transition'); 36 }); 37 // lazyload media of selected slide/prev slide/next slide 38 modal.slideshow.addEventListener('newItemSelected', function(event){ 39 // 'newItemSelected' is emitted by the Slideshow object when a new slide is selected 40 var prevSelected = modal.selectedSlide; 41 modal.selectedSlide = event.detail; 42 lazyLoadSlide(modal); 43 resetVideos(modal, prevSelected); // pause video of previous visible slide and start new video (if present) 44 resetIframes(modal, prevSelected); 45 updateThumb(modal); 46 }); 47 }; 48 49 function lazyLoadSlide(modal) { 50 setSlideMedia(modal, modal.selectedSlide); 51 setSlideMedia(modal, modal.selectedSlide + 1); 52 setSlideMedia(modal, modal.selectedSlide - 1); 53 }; 54 55 function setSlideMedia(modal, index) { 56 if(index < 0) index = modal.slides.length - 1; 57 if(index > modal.slides.length - 1) index = 0; 58 setSlideImgs(modal, index); 59 setSlidesVideos(modal, index, 'video'); 60 setSlidesVideos(modal, index, 'iframe'); 61 }; 62 63 function setSlideImgs(modal, index) { 64 var imgs = modal.slides[index].querySelectorAll('img[data-src]'); 65 for(var i = 0; i < imgs.length; i++) { 66 imgs[i].src = imgs[i].getAttribute('data-src'); 67 } 68 }; 69 70 function setSlidesVideos(modal, index, type) { 71 var videos = modal.slides[index].querySelectorAll(type+'[data-src]'); 72 for(var i = 0; i < videos.length; i++) { 73 videos[0].src = videos[0].getAttribute('data-src'); 74 videos[0].removeAttribute('data-src'); 75 } 76 }; 77 78 function initSlideshow(modal) { 79 if(modal.slides.length <= 1) { 80 hideSlideshowElements(modal); 81 return; 82 } 83 var swipe = (modal.slideshow.getAttribute('data-swipe') && modal.slideshow.getAttribute('data-swipe') == 'on') ? true : false; 84 modal.slideshowObj = new Slideshow({element: modal.slideshow, navigation: false, autoplay : false, swipe : swipe}); 85 }; 86 87 function hideSlideshowElements(modal) { // hide slideshow controls if gallery is composed by one item only 88 var slideshowNav = modal.element.getElementsByClassName('js-slideshow__control'); 89 if(slideshowNav.length > 0) { 90 for(var i = 0; i < slideshowNav.length; i++) Util.addClass(slideshowNav[i], 'is-hidden'); 91 } 92 var slideshowThumbs = modal.element.getElementsByClassName('js-lightbox_footer'); 93 if(slideshowThumbs.length > 0) Util.addClass(slideshowThumbs[0], 'is-hidden'); 94 }; 95 96 function resetVideos(modal, index) { 97 if(index) { 98 var actualVideo = modal.slides[index].getElementsByTagName('video'); 99 if(actualVideo.length > 0 ) actualVideo[0].pause(); 100 } 101 var newVideo = modal.slides[modal.selectedSlide].getElementsByTagName('video'); 102 if(newVideo.length > 0 ) { 103 setVideoWidth(modal, modal.selectedSlide, newVideo[0]); 104 newVideo[0].play(); 105 } 106 }; 107 108 function resetIframes(modal, index) { 109 if(index) { 110 var actualIframe = modal.slides[index].getElementsByTagName('iframe'); 111 if(actualIframe.length > 0 ) { 112 actualIframe[0].setAttribute('data-src', actualIframe[0].src); 113 actualIframe[0].removeAttribute('src'); 114 } 115 } 116 var newIframe = modal.slides[modal.selectedSlide].getElementsByTagName('iframe'); 117 if(newIframe.length > 0 ) { 118 setVideoWidth(modal, modal.selectedSlide, newIframe[0]); 119 } 120 }; 121 122 function resizeLightbox(modal) { // executed when window has been resized 123 if(!modal.selectedSlide) return; // modal not active 124 var video = modal.slides[modal.selectedSlide].getElementsByTagName('video'); 125 if(video.length > 0 ) setVideoWidth(modal, modal.selectedSlide, video[0]); 126 var iframe = modal.slides[modal.selectedSlide].getElementsByTagName('iframe'); 127 if(iframe.length > 0 ) setVideoWidth(modal, modal.selectedSlide, iframe[0]); 128 }; 129 130 function setVideoWidth(modal, index, video) { 131 var videoContainer = modal.slides[index].getElementsByClassName('js-lightbox__media-outer'); 132 if(videoContainer.length == 0 ) return; 133 var videoWrapper = videoContainer[0].getElementsByClassName('js-lightbox__media-inner'); 134 var maxWidth = (video.offsetWidth/video.offsetHeight)*videoContainer[0].offsetHeight; 135 if(maxWidth < modal.slides[index].offsetWidth) { 136 videoWrapper[0].style.width = maxWidth+'px'; 137 videoWrapper[0].style.paddingBottom = videoContainer[0].offsetHeight+'px'; 138 } else { 139 videoWrapper[0].removeAttribute('style') 140 } 141 }; 142 143 function initThumbPreview(modal) { 144 if(modal.thumbWrapper.length < 1) return; 145 var content = ''; 146 for(var i = 0; i < modal.slides.length; i++) { 147 var activeClass = Util.hasClass(modal.slides[i], 'slideshow__item--selected') ? ' lightbox__thumb--active': ''; 148 content = content + '<li class="lightbox__thumb js-lightbox__thumb'+activeClass+'"><img src="'+modal.slides[i].querySelector('[data-thumb]').getAttribute('data-thumb')+'">'+'</li>'; 149 } 150 modal.thumbWrapper[0].innerHTML = content; 151 }; 152 153 function initThumbEvents(modal) { 154 if(modal.thumbWrapper.length < 1) return; 155 modal.thumbSlides = modal.thumbWrapper[0].getElementsByClassName('js-lightbox__thumb'); 156 modal.thumbWrapper[0].addEventListener('click', function(event){ 157 var selectedThumb = event.target.closest('.js-lightbox__thumb'); 158 if(!selectedThumb || Util.hasClass(selectedThumb, 'lightbox__thumb--active')) return; 159 modal.slideshowObj.showItem(Util.getIndexInArray(modal.thumbSlides, selectedThumb)); 160 }); 161 }; 162 163 function updateThumb(modal) { 164 if(modal.thumbWrapper.length < 1) return; 165 // update selected thumb classes 166 var selectedThumb = modal.thumbWrapper[0].getElementsByClassName('lightbox__thumb--active'); 167 if(selectedThumb.length > 0) Util.removeClass(selectedThumb[0], 'lightbox__thumb--active'); 168 Util.addClass(modal.thumbSlides[modal.selectedSlide], 'lightbox__thumb--active'); 169 // update thumb list position (if selected thumb is outside viewport) 170 var offsetThumb = modal.thumbSlides[modal.selectedSlide].getBoundingClientRect(), 171 offsetThumbList = modal.thumbWrapper[0].getBoundingClientRect(); 172 if(offsetThumb.left < offsetThumbList.left) { 173 modal.thumbWrapper[0].scrollTo(modal.thumbSlides[modal.selectedSlide].offsetLeft - offsetThumbList.left, 0); 174 } else if(offsetThumb.right > offsetThumbList.right) { 175 modal.thumbWrapper[0].scrollTo( (offsetThumb.right - offsetThumbList.right) + modal.thumbWrapper[0].scrollLeft, 0); 176 } 177 }; 178 179 function keyboardNavigateLightbox(modal, direction) { 180 if(!Util.hasClass(modal.element, 'modal--is-visible')) return; 181 if(!document.activeElement.closest('.js-lightbox__body') && document.activeElement.closest('.js-modal')) return 182 (direction == 'next') ? modal.slideshowObj.showNext() : modal.slideshowObj.showPrev(); 183 }; 184 185 function setSelectedItem(modal, event) { 186 // if a specific slide was selected -> make sure to show that item first 187 var selectedItemId = false;
188 if(event.detail) { 189 var elTarget = event.detail.closest('[aria-controls="'+modal.id+'"]'); 190 if(elTarget) selectedItemId = elTarget.getAttribute('data-lightbox-item'); 191 } 192 193 if(!selectedItemId || !modal.slideshowObj) return; 194 var selectedItem = document.getElementById(selectedItemId); 195 if(!selectedItem) return; 196 var lastSelected = modal.slideshow.getElementsByClassName('slideshow__item--selected'); 197 if(lastSelected.length > 0 ) Util.removeClass(lastSelected[0], 'slideshow__item--selected'); 198 Util.addClass(selectedItem, 'slideshow__item--selected'); 199 }; 200 201 window.Lightbox = Lightbox; 202 203 // init Lightbox objects 204 var lightBoxes = document.getElementsByClassName('js-lightbox'); 205 if( lightBoxes.length > 0 ) { 206 var lightBoxArray = []; 207 for( var i = 0; i < lightBoxes.length; i++) { 208 (function(i){ lightBoxArray.push(new Lightbox(lightBoxes[i]));})(i); 209 210 // resize video/iframe 211 var resizingId = false; 212 window.addEventListener('resize', function(event){ 213 clearTimeout(resizingId); 214 resizingId = setTimeout(doneResizing, 300); 215 }); 216 217 function doneResizing() { 218 for( var i = 0; i < lightBoxArray.length; i++) { 219 (function(i){resizeLightbox(lightBoxArray[i]);})(i); 220 }; 221 }; 222 223 // Lightbox gallery navigation with keyboard 224 window.addEventListener('keydown', function(event){ 225 if(event.keyCode && event.keyCode == 39 || event.key && event.key.toLowerCase() == 'arrowright') { 226 updateLightbox('next'); 227 } else if(event.keyCode && event.keyCode == 37 || event.key && event.key.toLowerCase() == 'arrowleft') { 228 updateLightbox('prev'); 229 } 230 }); 231 232 function updateLightbox(direction) { 233 for( var i = 0; i < lightBoxArray.length; i++) { 234 (function(i){keyboardNavigateLightbox(lightBoxArray[i], direction);})(i); 235 }; 236 }; 237 } 238 } 239}());
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.