1/** 2 * How far beyond the currently displayed image to buffer. 3 * 4 * @type {number} 5 */ 6const carouselBufferSize = 1; 7 8const properties = { 9 sizesBackup: 'originalSizes', 10 resizeFlag: 'hasEventToUpdateFullscreenOnResize', 11}; 12 13const classes = { 14 opener: 'opener', 15 opened: 'opener-opened', 16 image: 'opener-image', 17 container: 'figure-img-container', 18 carousel: 'carousel', 19 item: 'carousel-item', 20 modal: 'modal-open', 21 activeItem: 'active', 22}; 23 24const selectors = { 25 body: 'body', 26 opener: '.' + classes.opener, 27 opened: '.' + classes.opened, 28 image: '.' + classes.image + ' img', 29 container: '.' + classes.container, 30 carousel: '.' + classes.carousel, 31 item: '.' + classes.item, 32 buttonOpen: '.' + classes.opener + ' .opener-button.opener-button-open, .' + classes.opener + ' .' + classes.image + ' img', 33 buttonClose: '.' + classes.opener + ' .opener-button.opener-button-close', 34}; 35 36let $buttonOpen = $(selectors.buttonOpen); 37let $buttonClose = $(selectors.buttonClose); 38 39const $carousels = $(selectors.carousel); 40 41/** 42 * @param {jQuery} $container 43 */ 44const findImage = function($container) { 45 return $container.find(selectors.image); 46}; 47 48/** 49 * If `index` goes outside of the boundaries of 0 and `length`-1, loop it back in. 50 * 51 * @param {number} index 52 * @param {number} length 53 * @returns {number} 54 */ 55const advanceInLoop = function (index, length) { 56 index = index % length; 57 return (index < 0) ? index + length : index 58}; 59 60/** 61 * If image opener is part of a carousel, choose the carousel. 62 * 63 * @param {jQuery} $opener 64 * @returns {jQuery} 65 */ 66const assignOpener = function($opener) { 67 const $carousel = $opener.closest(selectors.carousel); 68 69 return ($carousel.length > 0) ? $carousel : $opener; 70}; 71 72/** 73 * Whether this element is the child of an opener that is opened. 74 * 75 * @param {jQuery} $el 76 * @returns {boolean} 77 */ 78const isOpened = function($el) { 79 return ($el.closest(selectors.opened).length > 0); 80}; 81 82/** 83 * Whether this element is the child of a carousel item that is inactive. 84 * 85 * @param {jQuery} $el 86 * @returns {boolean} 87 */ 88const isInInactiveCarouselItem = function($el) { 89 const $item = $el.closest(selectors.item); 90 91 return ($item.length >
91 0) ? ! $item.hasClass(classes.activeItem) : false; 92}; 93 94/** 95 * @param {jQuery} $canvas Element which the image is scaled to fit inside. 96 * @param {jQuery} $image The image to be scaled. 97 * 98 * @returns {number} Percentage of viewport width 99 */ 100const getFullscreenImageWidth = function($canvas, $image) { 101 const 102 canvasRatio = $canvas.width() / $canvas.height(), 103 imageRatio = ($image.attr('width') > 0 && $image.attr('height') > 0) 104 ? $image.attr('width') / $image.attr('height') 105 : $image[0].naturalWidth / $image[0].naturalHeight, 106 canvasFractionOfViewport = $canvas.width() / $(window).width(); 107 108 // Width as fraction of canvas width. If image is more portrait-sized than the canvas, take the height into consideration. 109 const maxWidth = (imageRatio < canvasRatio) ? imageRatio / canvasRatio : 1.0; 110 111 return maxWidth * canvasFractionOfViewport * 100; 112}; 113 114/** 115 * @param {jQuery} $container 116 * @param {jQuery|undefined} $image The image to be scaled. If undefined, get image from $container instead. 117 */ 118const applyFullscreenResolution = function ($container, $image = undefined) { 119 if ($image === undefined) { 120 $image = findImage($container); 121 } 122 123 // Backup original value before changing. 124 if ($image.data(properties.sizesBackup) === undefined) { 125 $image.data(properties.sizesBackup, $image.attr('sizes')); 126 } 127 128 const $canvas = $container.find(selectors.container); 129 130 $image.attr('sizes', getFullscreenImageWidth($canvas, $image).toFixed(2) + 'vw'); 131 132 // Add event to update on resize. Only add once per image! 133 if ($image.data(properties.resizeFlag) === true) { 134 return; 135 } 136 $(window).resize({image: $image}, function(e) { 137 const $image = e.data.image; 138 if (isOpened($image) && !isInInactiveCarouselItem($image)) { 139 applyFullscreenResolution($image.closest(selectors.opener)); 140 } 141 }); 142 $image.data(properties.resizeFlag, true); 143}; 144 145/** 146 * @param {jQuery} $container 147 */ 148const removeFullscreenResolution = function ($container) { 149 const $image = findImage($container); 150 151 // Restore backup:ed value. 152 $image.attr('sizes', $image.data(properties.sizesBackup)); 153 $image.data(properties.sizesBackup, undefined); 154}; 155 156/** 157 * @param {Event} e 158 */ 159const applyFullscreenOnCarouselSlide = function (e) { 160 if (!isOpened($(e.target))) { 161 return; 162 } 163 164 const $items = $(e.target).find(selectors.item); 165 166 /** 167 * 1 for sliding forward (right), -1 for sliding backward (left). 168 * 169 * @type {number} 170 */ 171 const slideDirection = (e.from + 1 === e.to || (e.to === 0 && e.from !== 1)) ? 1 : -1; 172 173 for (let steps = 1; steps - 1 <= carouselBufferSize; steps++) { 174 const 175 currentIndex = e.from, 176 destinationIndex = advanceInLoop(currentIndex + (steps * slideDirection), $items.length), 177 $container = $items.eq(currentIndex), 178 $image = findImage($items.eq(destinationIndex)); 179 180 /** 181 * $image may be an image currently off-screen, but $container needs to belong to the image currently on-screen. 182 * This is because the container of an off-screen image has no physical dimensions yet. 183 */ 184 applyFullscreenResolution($container, $image); 185 } 186}; 187 188// Image opener 189$(document).on("click", selectors.buttonOpen, function () { 190 $buttonOpen = $(selectors.buttonOpen); 191 $buttonClose = $(selectors.buttonClose); 192 193 const $opener = $(this).closest('.opener'); 194 195 if ($opener.length > 0){ 196 var disabledValue = $opener.attr("disabled"); 197 if (disabledValue == "true" || disabledValue == "disabled") return; 198 } 199
200 $(selectors.body).addClass(classes.modal); 201 assignOpener($opener).addClass(classes.opened); 202 applyFullscreenResolution($opener); 203}); 204 205$(document).on("click", selectors.buttonClose, function () { 206 $buttonOpen = $(selectors.buttonOpen); 207 $buttonClose = $(selectors.buttonClose); 208 209 const $opener = $(this).closest('.opener'); 210 211 $(selectors.body).removeClass(classes.modal); 212 assignOpener($opener).removeClass(classes.opened); 213 removeFullscreenResolution($opener); 214}); 215 216$(document).keydown(function (e) { 217 if (e.keyCode === 27) { 218 $buttonClose.click(); 219 } 220}); 221 222$carousels.on('slide.bs.carousel', applyFullscreenOnCarouselSlide);
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.