[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 import * as __WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__ from "@wordpress/interactivity"; 2 /******/ // The require scope 3 /******/ var __webpack_require__ = {}; 4 /******/ 5 /************************************************************************/ 6 /******/ /* webpack/runtime/define property getters */ 7 /******/ (() => { 8 /******/ // define getter functions for harmony exports 9 /******/ __webpack_require__.d = (exports, definition) => { 10 /******/ for(var key in definition) { 11 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 12 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 13 /******/ } 14 /******/ } 15 /******/ }; 16 /******/ })(); 17 /******/ 18 /******/ /* webpack/runtime/hasOwnProperty shorthand */ 19 /******/ (() => { 20 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 21 /******/ })(); 22 /******/ 23 /************************************************************************/ 24 var __webpack_exports__ = {}; 25 26 ;// CONCATENATED MODULE: external "@wordpress/interactivity" 27 var x = (y) => { 28 var x = {}; __webpack_require__.d(x, y); return x 29 } 30 var y = (x) => (() => (x)) 31 const interactivity_namespaceObject = x({ ["getContext"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.getContext), ["getElement"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.getElement), ["store"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.store) }); 32 ;// CONCATENATED MODULE: ./node_modules/@wordpress/block-library/build-module/image/view.js 33 /** 34 * WordPress dependencies 35 */ 36 37 38 /** 39 * Tracks whether user is touching screen; used to differentiate behavior for 40 * touch and mouse input. 41 * 42 * @type {boolean} 43 */ 44 let isTouching = false; 45 46 /** 47 * Tracks the last time the screen was touched; used to differentiate behavior 48 * for touch and mouse input. 49 * 50 * @type {number} 51 */ 52 let lastTouchTime = 0; 53 54 /** 55 * Stores the image reference of the currently opened lightbox. 56 * 57 * @type {HTMLElement} 58 */ 59 let imageRef; 60 61 /** 62 * Stores the button reference of the currently opened lightbox. 63 * 64 * @type {HTMLElement} 65 */ 66 let buttonRef; 67 const { 68 state, 69 actions, 70 callbacks 71 } = (0,interactivity_namespaceObject.store)('core/image', { 72 state: { 73 currentImage: {}, 74 get overlayOpened() { 75 return state.currentImage.currentSrc; 76 }, 77 get roleAttribute() { 78 return state.overlayOpened ? 'dialog' : null; 79 }, 80 get ariaModal() { 81 return state.overlayOpened ? 'true' : null; 82 }, 83 get enlargedSrc() { 84 return state.currentImage.uploadedSrc || 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; 85 }, 86 get imgStyles() { 87 return state.overlayOpened && `$state.currentImage.imgStyles?.replace(/;$/, '')}; object-fit:cover;`; 88 } 89 }, 90 actions: { 91 showLightbox() { 92 const ctx = (0,interactivity_namespaceObject.getContext)(); 93 94 // Bails out if the image has not loaded yet. 95 if (!ctx.imageRef?.complete) { 96 return; 97 } 98 99 // Stores the positons of the scroll to fix it until the overlay is 100 // closed. 101 state.scrollTopReset = document.documentElement.scrollTop; 102 state.scrollLeftReset = document.documentElement.scrollLeft; 103 104 // Moves the information of the expaned image to the state. 105 ctx.currentSrc = ctx.imageRef.currentSrc; 106 imageRef = ctx.imageRef; 107 buttonRef = ctx.buttonRef; 108 state.currentImage = ctx; 109 state.overlayEnabled = true; 110 111 // Computes the styles of the overlay for the animation. 112 callbacks.setOverlayStyles(); 113 }, 114 hideLightbox() { 115 if (state.overlayEnabled) { 116 // Waits until the close animation has completed before allowing a 117 // user to scroll again. The duration of this animation is defined in 118 // the `styles.scss` file, but in any case we should wait a few 119 // milliseconds longer than the duration, otherwise a user may scroll 120 // too soon and cause the animation to look sloppy. 121 setTimeout(function () { 122 // Delays before changing the focus. Otherwise the focus ring will 123 // appear on Firefox before the image has finished animating, which 124 // looks broken. 125 buttonRef.focus({ 126 preventScroll: true 127 }); 128 129 // Resets the current image to mark the overlay as closed. 130 state.currentImage = {}; 131 imageRef = null; 132 buttonRef = null; 133 }, 450); 134 135 // Starts the overlay closing animation. The showClosingAnimation 136 // class is used to avoid showing it on page load. 137 state.showClosingAnimation = true; 138 state.overlayEnabled = false; 139 } 140 }, 141 handleKeydown(event) { 142 if (state.overlayEnabled) { 143 // Focuses the close button when the user presses the tab key. 144 if (event.key === 'Tab') { 145 event.preventDefault(); 146 const { 147 ref 148 } = (0,interactivity_namespaceObject.getElement)(); 149 ref.querySelector('button').focus(); 150 } 151 // Closes the lightbox when the user presses the escape key. 152 if (event.key === 'Escape') { 153 actions.hideLightbox(); 154 } 155 } 156 }, 157 handleTouchMove(event) { 158 // On mobile devices, prevents triggering the scroll event because 159 // otherwise the page jumps around when it resets the scroll position. 160 // This also means that closing the lightbox requires that a user 161 // perform a simple tap. This may be changed in the future if there is a 162 // better alternative to override or reset the scroll position during 163 // swipe actions. 164 if (state.overlayEnabled) { 165 event.preventDefault(); 166 } 167 }, 168 handleTouchStart() { 169 isTouching = true; 170 }, 171 handleTouchEnd() { 172 // Waits a few milliseconds before resetting to ensure that pinch to 173 // zoom works consistently on mobile devices when the lightbox is open. 174 lastTouchTime = Date.now(); 175 isTouching = false; 176 }, 177 handleScroll() { 178 // Prevents scrolling behaviors that trigger content shift while the 179 // lightbox is open. It would be better to accomplish through CSS alone, 180 // but using overflow: hidden is currently the only way to do so and 181 // that causes a layout to shift and prevents the zoom animation from 182 // working in some cases because it's not possible to account for the 183 // layout shift when doing the animation calculations. Instead, it uses 184 // JavaScript to prevent and reset the scrolling behavior. 185 if (state.overlayOpened) { 186 // Avoids overriding the scroll behavior on mobile devices because 187 // doing so breaks the pinch to zoom functionality, and users should 188 // be able to zoom in further on the high-res image. 189 if (!isTouching && Date.now() - lastTouchTime > 450) { 190 // It doesn't rely on `event.preventDefault()` to prevent scrolling 191 // because the scroll event can't be canceled, so it resets the 192 // position instead. 193 window.scrollTo(state.scrollLeftReset, state.scrollTopReset); 194 } 195 } 196 } 197 }, 198 callbacks: { 199 setOverlayStyles() { 200 if (!imageRef) return; 201 let { 202 naturalWidth, 203 naturalHeight, 204 offsetWidth: originalWidth, 205 offsetHeight: originalHeight 206 } = imageRef; 207 let { 208 x: screenPosX, 209 y: screenPosY 210 } = imageRef.getBoundingClientRect(); 211 212 // Natural ratio of the image clicked to open the lightbox. 213 const naturalRatio = naturalWidth / naturalHeight; 214 // Original ratio of the image clicked to open the lightbox. 215 let originalRatio = originalWidth / originalHeight; 216 217 // If it has object-fit: contain, recalculates the original sizes 218 // and the screen position without the blank spaces. 219 if (state.currentImage.scaleAttr === 'contain') { 220 if (naturalRatio > originalRatio) { 221 const heightWithoutSpace = originalWidth / naturalRatio; 222 // Recalculates screen position without the top space. 223 screenPosY += (originalHeight - heightWithoutSpace) / 2; 224 originalHeight = heightWithoutSpace; 225 } else { 226 const widthWithoutSpace = originalHeight * naturalRatio; 227 // Recalculates screen position without the left space. 228 screenPosX += (originalWidth - widthWithoutSpace) / 2; 229 originalWidth = widthWithoutSpace; 230 } 231 } 232 originalRatio = originalWidth / originalHeight; 233 234 // Typically, it uses the image's full-sized dimensions. If those 235 // dimensions have not been set (i.e. an external image with only one 236 // size), the image's dimensions in the lightbox are the same 237 // as those of the image in the content. 238 let imgMaxWidth = parseFloat(state.currentImage.targetWidth !== 'none' ? state.currentImage.targetWidth : naturalWidth); 239 let imgMaxHeight = parseFloat(state.currentImage.targetHeight !== 'none' ? state.currentImage.targetHeight : naturalHeight); 240 241 // Ratio of the biggest image stored in the database. 242 let imgRatio = imgMaxWidth / imgMaxHeight; 243 let containerMaxWidth = imgMaxWidth; 244 let containerMaxHeight = imgMaxHeight; 245 let containerWidth = imgMaxWidth; 246 let containerHeight = imgMaxHeight; 247 // Checks if the target image has a different ratio than the original 248 // one (thumbnail). Recalculates the width and height. 249 if (naturalRatio.toFixed(2) !== imgRatio.toFixed(2)) { 250 if (naturalRatio > imgRatio) { 251 // If the width is reached before the height, it keeps the maxWidth 252 // and recalculates the height unless the difference between the 253 // maxHeight and the reducedHeight is higher than the maxWidth, 254 // where it keeps the reducedHeight and recalculate the width. 255 const reducedHeight = imgMaxWidth / naturalRatio; 256 if (imgMaxHeight - reducedHeight > imgMaxWidth) { 257 imgMaxHeight = reducedHeight; 258 imgMaxWidth = reducedHeight * naturalRatio; 259 } else { 260 imgMaxHeight = imgMaxWidth / naturalRatio; 261 } 262 } else { 263 // If the height is reached before the width, it keeps the maxHeight 264 // and recalculate the width unlesss the difference between the 265 // maxWidth and the reducedWidth is higher than the maxHeight, where 266 // it keeps the reducedWidth and recalculate the height. 267 const reducedWidth = imgMaxHeight * naturalRatio; 268 if (imgMaxWidth - reducedWidth > imgMaxHeight) { 269 imgMaxWidth = reducedWidth; 270 imgMaxHeight = reducedWidth / naturalRatio; 271 } else { 272 imgMaxWidth = imgMaxHeight * naturalRatio; 273 } 274 } 275 containerWidth = imgMaxWidth; 276 containerHeight = imgMaxHeight; 277 imgRatio = imgMaxWidth / imgMaxHeight; 278 279 // Calculates the max size of the container. 280 if (originalRatio > imgRatio) { 281 containerMaxWidth = imgMaxWidth; 282 containerMaxHeight = containerMaxWidth / originalRatio; 283 } else { 284 containerMaxHeight = imgMaxHeight; 285 containerMaxWidth = containerMaxHeight * originalRatio; 286 } 287 } 288 289 // If the image has been pixelated on purpose, it keeps that size. 290 if (originalWidth > containerWidth || originalHeight > containerHeight) { 291 containerWidth = originalWidth; 292 containerHeight = originalHeight; 293 } 294 295 // Calculates the final lightbox image size and the scale factor. 296 // MaxWidth is either the window container (accounting for padding) or 297 // the image resolution. 298 let horizontalPadding = 0; 299 if (window.innerWidth > 480) { 300 horizontalPadding = 80; 301 } else if (window.innerWidth > 1920) { 302 horizontalPadding = 160; 303 } 304 const verticalPadding = 80; 305 const targetMaxWidth = Math.min(window.innerWidth - horizontalPadding, containerWidth); 306 const targetMaxHeight = Math.min(window.innerHeight - verticalPadding, containerHeight); 307 const targetContainerRatio = targetMaxWidth / targetMaxHeight; 308 if (originalRatio > targetContainerRatio) { 309 // If targetMaxWidth is reached before targetMaxHeight. 310 containerWidth = targetMaxWidth; 311 containerHeight = containerWidth / originalRatio; 312 } else { 313 // If targetMaxHeight is reached before targetMaxWidth. 314 containerHeight = targetMaxHeight; 315 containerWidth = containerHeight * originalRatio; 316 } 317 const containerScale = originalWidth / containerWidth; 318 const lightboxImgWidth = imgMaxWidth * (containerWidth / containerMaxWidth); 319 const lightboxImgHeight = imgMaxHeight * (containerHeight / containerMaxHeight); 320 321 // As of this writing, using the calculations above will render the 322 // lightbox with a small, erroneous whitespace on the left side of the 323 // image in iOS Safari, perhaps due to an inconsistency in how browsers 324 // handle absolute positioning and CSS transformation. In any case, 325 // adding 1 pixel to the container width and height solves the problem, 326 // though this can be removed if the issue is fixed in the future. 327 state.overlayStyles = ` 328 :root { 329 --wp--lightbox-initial-top-position: $screenPosY}px; 330 --wp--lightbox-initial-left-position: $screenPosX}px; 331 --wp--lightbox-container-width: $containerWidth + 1}px; 332 --wp--lightbox-container-height: $containerHeight + 1}px; 333 --wp--lightbox-image-width: $lightboxImgWidth}px; 334 --wp--lightbox-image-height: $lightboxImgHeight}px; 335 --wp--lightbox-scale: $containerScale}; 336 --wp--lightbox-scrollbar-width: $window.innerWidth - document.documentElement.clientWidth}px; 337 } 338 `; 339 }, 340 setButtonStyles() { 341 const ctx = (0,interactivity_namespaceObject.getContext)(); 342 const { 343 ref 344 } = (0,interactivity_namespaceObject.getElement)(); 345 ctx.imageRef = ref; 346 const { 347 naturalWidth, 348 naturalHeight, 349 offsetWidth, 350 offsetHeight 351 } = ref; 352 353 // If the image isn't loaded yet, it can't calculate where the button 354 // should be. 355 if (naturalWidth === 0 || naturalHeight === 0) { 356 return; 357 } 358 const figure = ref.parentElement; 359 const figureWidth = ref.parentElement.clientWidth; 360 361 // It needs special handling for the height because a caption will cause 362 // the figure to be taller than the image, which means it needs to 363 // account for that when calculating the placement of the button in the 364 // top right corner of the image. 365 let figureHeight = ref.parentElement.clientHeight; 366 const caption = figure.querySelector('figcaption'); 367 if (caption) { 368 const captionComputedStyle = window.getComputedStyle(caption); 369 if (!['absolute', 'fixed'].includes(captionComputedStyle.position)) { 370 figureHeight = figureHeight - caption.offsetHeight - parseFloat(captionComputedStyle.marginTop) - parseFloat(captionComputedStyle.marginBottom); 371 } 372 } 373 const buttonOffsetTop = figureHeight - offsetHeight; 374 const buttonOffsetRight = figureWidth - offsetWidth; 375 376 // In the case of an image with object-fit: contain, the size of the 377 // <img> element can be larger than the image itself, so it needs to 378 // calculate where to place the button. 379 if (ctx.scaleAttr === 'contain') { 380 // Natural ratio of the image. 381 const naturalRatio = naturalWidth / naturalHeight; 382 // Offset ratio of the image. 383 const offsetRatio = offsetWidth / offsetHeight; 384 if (naturalRatio >= offsetRatio) { 385 // If it reaches the width first, it keeps the width and compute the 386 // height. 387 const referenceHeight = offsetWidth / naturalRatio; 388 ctx.imageButtonTop = (offsetHeight - referenceHeight) / 2 + buttonOffsetTop + 16; 389 ctx.imageButtonRight = buttonOffsetRight + 16; 390 } else { 391 // If it reaches the height first, it keeps the height and compute 392 // the width. 393 const referenceWidth = offsetHeight * naturalRatio; 394 ctx.imageButtonTop = buttonOffsetTop + 16; 395 ctx.imageButtonRight = (offsetWidth - referenceWidth) / 2 + buttonOffsetRight + 16; 396 } 397 } else { 398 ctx.imageButtonTop = buttonOffsetTop + 16; 399 ctx.imageButtonRight = buttonOffsetRight + 16; 400 } 401 }, 402 setOverlayFocus() { 403 if (state.overlayEnabled) { 404 // Moves the focus to the dialog when it opens. 405 const { 406 ref 407 } = (0,interactivity_namespaceObject.getElement)(); 408 ref.focus(); 409 } 410 }, 411 initTriggerButton() { 412 const ctx = (0,interactivity_namespaceObject.getContext)(); 413 const { 414 ref 415 } = (0,interactivity_namespaceObject.getElement)(); 416 ctx.buttonRef = ref; 417 } 418 } 419 }, { 420 lock: true 421 }); 422
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Sat Apr 27 08:20:02 2024 | Cross-referenced by PHPXref |