vendor: 5,537 bytes, lines 1-218
1var BigPicture = (function () { 2 // BigPicture.js | license MIT | henrygd.me/bigpicture 3 4 // trigger element used to open popup 5 var el; 6 7 // set to true after first interaction 8 var initialized; 9 10 // container element holding html needed for script 11 var container; 12 13 // currently active display element (image, video, youtube / vimeo iframe container) 14 var displayElement; 15 16 // popup image element 17 var displayImage; 18 19 // popup video element 20 var displayVideo; 21 22 // popup audio element 23 var displayAudio; 24 25 // container element to hold youtube / vimeo iframe 26 var iframeContainer; 27 28 // iframe to hold youtube / vimeo player 29 var iframeSiteVid; 30 31 // store requested image source 32 var imgSrc; 33 34 // button that closes the container 35 var closeButton; 36 37 // youtube / vimeo video id 38 var siteVidID; 39 40 // keeps track of loading icon display state 41 var isLoading; 42 43 // timeout to check video status while loading 44 var checkMediaTimeout; 45 46 // loading icon element 47 var loadingIcon; 48 49 // caption element 50 var caption; 51 52 // caption content element 53 var captionText; 54 55 // store caption content 56 var captionContent; 57 58 // hide caption button element 59 var captionHideButton; 60 61 // open state for container element 62 var isOpen; 63 64 // gallery open state 65 var galleryOpen; 66 67 // used during close animation to avoid triggering timeout twice 68 var isClosing; 69 70 // array of prev viewed image urls to check if cached before showing loading icon 71 var imgCache = []; 72 73 // store whether image requested is remote or local 74 var remoteImage; 75 76 // store animation opening callbacks 77 var animationStart; 78 var animationEnd; 79 80 // store changeGalleryImage callback 81 var onChangeImage; 82 83 // gallery left / right icons 84 var rightArrowBtn; 85 86 var leftArrowBtn; 87 88 // position of gallery 89 var galleryPosition; 90 91 // hold active gallery els / image src 92 var galleryEls; 93 94 // counter element 95 var galleryCounter; 96 97 // store images in gallery that are being loaded 98 var preloadedImages = {}; 99 100 // whether device supports touch events 101 var supportsTouch; 102 103 // options object 104 var opts; 105 106 // Save bytes in the minified version 107 var appendEl = 'appendChild'; 108 var createEl = 'createElement'; 109 var removeEl = 'removeChild'; 110 111 function BigPicture (options) { 112 // initialize called on initial open to create elements / style / event handlers 113 initialized || initialize(); 114 115 // clear currently loading stuff 116 if (isLoading) { 117 clearTimeout(checkMediaTimeout); 118 removeContainer(); 119 } 120 121 opts = options; 122 123 // store video id if youtube / vimeo video is requested 124 siteVidID = options.ytSrc || options.vimeoSrc; 125 126 // store optional callbacks 127 animationStart = options.animationStart; 128 animationEnd = options.animationEnd; 129 onChangeImage = options.onChangeImage; 130 131 // set trigger element 132 el = options.el; 133 134 // wipe existing remoteImage state 135 remoteImage = false; 136 137 // set caption if provided 138 captionContent = el.getAttribute('data-caption'); 139 140 if (options.gallery) { 141 makeGallery(options.gallery, options.position); 142 } else if (siteVidID || options.iframeSrc) { 143 // if vimeo, youtube, or iframe video 144 // toggleLoadingIcon(true) 145 displayElement = iframeContainer; 146 createIframe(); 147 } else if (options.imgSrc) { 148 // if remote image 149 remoteImage = true; 150 imgSrc = options.imgSrc; 151 !~imgCache.indexOf(imgSrc) && toggleLoadingIcon(true); 152 displayElement = displayImage; 153 displayElement.src = imgSrc; 154 } else if (options.audio) { 155 // if direct video link 156 toggleLoadingIcon(true); 157 displayElement = displayAudio; 158 displayElement.src = options.audio; 159 checkMedia('audio file'); 160 } else if (options.vidSrc) { 161 // if direct video link 162 toggleLoadingIcon(true); 163 if (options.dimensions) { 164 changeCSS(displayVideo, ("width:" + (options.dimensions[0]) + "px")); 165 } 166 makeVidSrc(options.vidSrc); 167 checkMedia('video'); 168 } else { 169 // local image / background image already loaded on page 170 displayElement = displayImage; 171 // get img source or element background image 172 displayElement.src = 173 el.tagName === 'IMG' 174 ? el.src 175 : window 176 .getComputedStyle(el) 177 .backgroundImage.replace(/^url|[(|)|'|"]/g, ''); 178 } 179 180 // add container to page 181 container[appendEl](displayElement); 182 document.body[appendEl](container); 183 return { 184 close: close, 185 next: function () { return updateGallery(1); }, 186 prev: function () { return updateGallery(-1); }, 187 } 188 } 189 190 // create all needed methods / store dom elements on first use 191 function initialize() { 192 var startX, isPinch; 193 // return close button elements 194 function createCloseButton(className) { 195 var el = document[createEl]('button'); 196 el.className = className; 197 el.innerHTML = 198 '<svg viewBox="0 0 48 48"><path d="M28 24L47 5a3 3 0 1 0-4-4L24 20 5 1a3 3 0 1 0-4 4l19 19L1 43a3 3 0 1 0 4 4l19-19 19 19a3 3 0 0 0 4 0v-4L28 24z"/></svg>'; 199 return el 200 } 201 202 function createArrowSymbol(direction, style) { 203 var el = document[createEl]('button'); 204 el.className = 'bp-lr'; 205 el.innerHTML = 206 '<svg viewBox="0 0 129 129" height="70" fill="#fff"><path d="M88.6 121.3c.8.8 1.8 1.2 2.9 1.2s2.1-.4 2.9-1.2a4.1 4.1 0 0 0 0-5.8l-51-51 51-51a4.1 4.1 0 0 0-5.8-5.8l-54 53.9a4.1 4.1 0 0 0 0 5.8l54 53.9z"/></svg>'; 207 changeCSS(el, style); 208 el.onclick = function (e) { 209 e.stopPropagation(); 210 updateGallery(direction); 211 }; 212 return el 213 } 214 215 // add style - if you want to tweak, run through beautifier 216 var style = document[createEl]('STYLE'); 217 style.innerHTML = 218 '#bp_caption,#bp_container{bottom:0;left:0;right:0;position:fixed;opacity:0}
218#bp_container>*,#bp_loader{position:absolute;right:0;z-index:10}#bp_container,#bp_caption,#bp_container svg{pointer-events:none}#bp_container{top:0;z-index:9999;background:rgba(0,0,0,.7);opacity:0;transition:opacity .35s}#bp_loader{top:0;left:0;bottom:0;display:flex;align-items:center;cursor:wait;background:0;z-index:9}#bp_loader svg{width:50%;max-width:300px;max-height:50%;margin:auto;animation:bpturn 1s infinite linear}#bp_aud,#bp_container img,#bp_sv,#bp_vid{user-select:none;max-height:96%;max-width:96%;top:0;bottom:0;left:0;margin:auto;box-shadow:0 0 3em rgba(0,0,0,.4);z-index:-1}#bp_sv{background:#111}#bp_sv svg{width:66px}#bp_caption{font-size:.9em;padding:1.3em;background:rgba(15,15,15,.94);color:#fff;text-align:center;transition:opacity .3s}#bp_aud{width:650px;top:calc(50% - 20px);bottom:auto;box-shadow:none}#bp_count{left:0;right:auto;padding:14px;color:rgba(255,255,255,.7);font-size:22px;cursor:default}#bp_container button{position:absolute;border:0;outline:0;background:0;cursor:pointer;transition:all .1s}#bp_container>.bp-x{padding:0;height:41px;width:41px;border-radius:100%;top:8px;right:14px;opacity:.8;line-height:1}#bp_container>.bp-x:focus,#bp_container>.bp-x:hover{background:rgba(255,255,255,.2)}.bp-x svg,.bp-xc svg{height:21px;width:20px;fill:#fff;vertical-align:top;}.bp-xc svg{width:16px}#bp_container .bp-xc{left:2%;bottom:100%;padding:9px 20px 7px;background:#d04444;border-radius:2px 2px 0 0;opacity:.85}#bp_container .bp-xc:focus,#bp_container .bp-xc:hover{opacity:1}.bp-lr{top:50%;top:calc(50% - 130px);padding:99px 0;width:6%;background:0;border:0;opacity:.4;transition:opacity .1s}.bp-lr:focus,.bp-lr:hover{opacity:.8}@keyframes bpf{50%{transform:translatex(15px)}100%{transform:none}}@keyframes bpl{50%{transform:translatex(-15px)}100%{transform:none}}@keyframes bpfl{0%{opacity:0;transform:translatex(70px)}100%{opacity:1;transform:none}}@keyframes bpfr{0%{opacity:0;transform:translatex(-70px)}100%{opacity:1;transform:none}}@keyframes bpfol{0%{opacity:1;transform:none}100%{opacity:0;transform:translatex(-70px)}}@keyframes bpfor{0%{opacity:1;transform:none}100%{opacity:0;transform:translatex(70px)}}@keyframes bpturn{0%{transform:none}100%{transform:rotate(360deg)}}@media (max-width:600px){.bp-lr{font-size:15vw}}'; 219 document.head[appendEl](style); 220 221 // create container element 222 container = document[createEl]('DIV'); 223 container.id = 'bp_container'; 224 container.onclick = close; 225 closeButton = createCloseButton('bp-x'); 226 container[appendEl](closeButton); 227 // gallery touch listeners 228 if ('ontouchend' in window && window.visualViewport) { 229 supportsTouch = true; 230 container.ontouchstart = function (ref) { 231 var touches = ref.touches; 232 var changedTouches = ref.changedTouches; 233 234 isPinch = touches.length > 1; 235 startX = changedTouches[0].pageX; 236 }; 237 container.ontouchend = function (ref) { 238 var changedTouches = ref.changedTouches; 239 240 if (galleryOpen && !isPinch && window.visualViewport.scale <= 1) { 241 var distX = changedTouches[0].pageX - startX; 242 // swipe right 243 distX < -30 && updateGallery(1); 244 // swipe left 245 distX > 30 && updateGallery(-1); 246 } 247 }; 248 } 249 250 // create display image element 251 displayImage = document[createEl]('IMG'); 252 253 // create display video element 254 displayVideo = document[createEl]('VIDEO'); 255 displayVideo.id = 'bp_vid'; 256 displayVideo.setAttribute('playsinline', true); 257 displayVideo.controls = true; 258 displayVideo.loop = true; 259 260 // create audio element 261 displayAudio = document[createEl]('audio'); 262 displayAudio.id = 'bp_aud'; 263 displayAudio.controls = true; 264 displayAudio.loop = true; 265 266 // create gallery counter 267 galleryCounter = document[createEl]('span'); 268 galleryCounter.id = 'bp_count'; 269 270 // create caption elements 271 caption = document[createEl]('DIV'); 272 caption.id = 'bp_caption'; 273 captionHideButton = createCloseButton('bp-xc'); 274 captionHideButton.onclick = toggleCaption.bind(null, false); 275 caption[appendEl](captionHideButton); 276 captionText = document[createEl]('SPAN'); 277 caption[appendEl](captionText); 278 container[appendEl](caption); 279 280 // left / right arrow icons 281 rightArrowBtn = createArrowSymbol(1, 'transform:scalex(-1)'); 282 leftArrowBtn = createArrowSymbol(-1, 'left:0;right:auto'); 283 284 // create loading icon element 285 loadingIcon = document[createEl]('DIV'); 286 loadingIcon.id = 'bp_loader'; 287 loadingIcon.innerHTML =
vendor: 1,162 bytes, lines 288-312
288 '<svg viewbox="0 0 32 32" fill="#fff" opacity=".8"><path d="M16 0a16 16 0 0 0 0 32 16 16 0 0 0 0-32m0 4a12 12 0 0 1 0 24 12 12 0 0 1 0-24" fill="#000" opacity=".5"/><path d="M16 0a16 16 0 0 1 16 16h-4A12 12 0 0 0 16 4z"/></svg>'; 289 // create youtube / vimeo container 290 iframeContainer = document[createEl]('DIV'); 291 iframeContainer.id = 'bp_sv'; 292 293 // create iframe to hold youtube / vimeo player 294 iframeSiteVid = document[createEl]('IFRAME'); 295 iframeSiteVid.setAttribute('allowfullscreen', true); 296 iframeSiteVid.allow = 'autoplay; fullscreen'; 297 iframeSiteVid.onload = function () { return iframeContainer[removeEl](loadingIcon); }; 298 changeCSS( 299 iframeSiteVid, 300 'border:0;position:absolute;height:100%;width:100%;left:0;top:0' 301 ); 302 iframeContainer[appendEl](iframeSiteVid); 303 304 // display image bindings for image load and error 305 displayImage.onload = open; 306 displayImage.onerror = open.bind(null, 'image'); 307 308 window.addEventListener('resize', function () { 309 // adjust loader position on window resize 310 galleryOpen || (isLoading && toggleLoadingIcon(true)); 311 // adjust iframe dimensions 312 displayElement === iframeContainer && updateIfram
vendor: 7,431 bytes, lines 312-551
312eDimensions(); 313 }); 314 315 // close container on escape key press and arrow buttons for gallery 316 document.addEventListener('keyup', function (ref) { 317 var keyCode = ref.keyCode; 318 319 keyCode === 27 && isOpen && close(); 320 if (galleryOpen) { 321 keyCode === 39 && updateGallery(1); 322 keyCode === 37 && updateGallery(-1); 323 keyCode === 38 && updateGallery(10); 324 keyCode === 40 && updateGallery(-10); 325 } 326 }); 327 // prevent scrolling with arrow keys if gallery open 328 document.addEventListener('keydown', function (e) { 329 var usedKeys = [37, 38, 39, 40]; 330 if (galleryOpen && ~usedKeys.indexOf(e.keyCode)) { 331 e.preventDefault(); 332 } 333 }); 334 335 // trap focus within conainer while open 336 document.addEventListener( 337 'focus', 338 function (e) { 339 if (isOpen && !container.contains(e.target)) { 340 e.stopPropagation(); 341 closeButton.focus(); 342 } 343 }, 344 true 345 ); 346 347 // all done 348 initialized = true; 349 } 350 351 // return transform style to make full size display el match trigger el size 352 function getRect() { 353 var ref = el.getBoundingClientRect(); 354 var top = ref.top; 355 var left = ref.left; 356 var width = ref.width; 357 var height = ref.height; 358 var leftOffset = left - (container.clientWidth - width) / 2; 359 var centerTop = top - (container.clientHeight - height) / 2; 360 var scaleWidth = el.clientWidth / displayElement.clientWidth; 361 var scaleHeight = el.clientHeight / displayElement.clientHeight; 362 return ("transform:translate3D(" + leftOffset + "px, " + centerTop + "px, 0) scale3D(" + scaleWidth + ", " + scaleHeight + ", 0)") 363 } 364 365 function makeVidSrc(source) { 366 if (Array.isArray(source)) { 367 displayElement = displayVideo.cloneNode(); 368 source.forEach(function (src) { 369 var source = document[createEl]('SOURCE'); 370 source.src = src; 371 source.type = "video/" + (src.match(/.(\w+)$/)[1]); 372 displayElement[appendEl](source); 373 }); 374 } else { 375 displayElement = displayVideo; 376 displayElement.src = source; 377 } 378 } 379 380 function makeGallery(gallery, position) { 381 var galleryAttribute = opts.galleryAttribute || 'data-bp'; 382 if (Array.isArray(gallery)) { 383 // is array of images 384 galleryPosition = position || 0; 385 galleryEls = gallery; 386 captionContent = gallery[galleryPosition].caption; 387 } else { 388 // is element selector or nodelist 389 galleryEls = [].slice.call( 390 typeof gallery === 'string' 391 ? document.querySelectorAll((gallery + " [" + galleryAttribute + "]")) 392 : gallery 393 ); 394 // find initial gallery position 395 var elIndex = galleryEls.indexOf(el); 396 galleryPosition = 397 position === 0 || position ? position : elIndex !== -1 ? elIndex : 0; 398 // make gallery object w/ els / src / caption 399 galleryEls = galleryEls.map(function (el) { return ({ 400 el: el, 401 src: el.getAttribute(galleryAttribute), 402 caption: el.getAttribute('data-caption'), 403 }); }); 404 } 405 // show loading icon if needed 406 remoteImage = true; 407 // set initial src to imgSrc so it will be cached in open func 408 imgSrc = galleryEls[galleryPosition].src; 409 !~imgCache.indexOf(imgSrc) && toggleLoadingIcon(true); 410 if (galleryEls.length > 1) { 411 // if length is greater than one, add gallery stuff 412 container[appendEl](galleryCounter); 413 galleryCounter.innerHTML = (galleryPosition + 1) + "/" + (galleryEls.length); 414 if (!supportsTouch) { 415 // add arrows if device doesn't support touch 416 container[appendEl](rightArrowBtn); 417 container[appendEl](leftArrowBtn); 418 } 419 } else { 420 // gallery is one, just show without clutter 421 galleryEls = false; 422 } 423 displayElement = displayImage; 424 // set initial image src 425 displayElement.src = imgSrc; 426 } 427 428 function updateGallery(movement) { 429 var galleryLength = galleryEls.length - 1; 430 431 // only allow one change at a time 432 if (isLoading) { 433 return 434 } 435 436 // return if requesting out of range image 437 var isEnd = 438 (movement > 0 && galleryPosition === galleryLength) || 439 (movement < 0 && !galleryPosition); 440 if (isEnd) { 441 // if beginning or end of gallery, run end animation 442 if (!opts.loop) { 443 changeCSS(displayImage, ''); 444 setTimeout( 445 changeCSS, 446 9, 447 displayImage, 448 ("animation:" + (movement > 0 ? 'bpl' : 'bpf') + " .3s;transition:transform .35s") 449 ); 450 return 451 } 452 // if gallery is looped, adjust position to beginning / end 453 galleryPosition = movement > 0 ? -1 : galleryLength + 1; 454 } 455 456 // normalize position 457 galleryPosition = Math.max( 458 0, 459 Math.min(galleryPosition + movement, galleryLength) 460 ) 461 462 // load images before and after for quicker scrolling through pictures 463 ;[galleryPosition - 1, galleryPosition, galleryPosition + 1].forEach( 464 function (position) { 465 // normalize position 466 position = Math.max(0, Math.min(position, galleryLength)); 467 // cancel if image has already been preloaded 468 if (preloadedImages[position]) { return } 469 var src = galleryEls[position].src; 470 // create image for preloadedImages 471 var img = document[createEl]('IMG'); 472 img.addEventListener('load', addToImgCache.bind(null, src)); 473 img.src = src; 474 preloadedImages[position] = img; 475 } 476 ); 477 // if image is loaded, show it 478 if (preloadedImages[galleryPosition].complete) { 479 return changeGalleryImage(movement) 480 } 481 // if not, show loading icon and change when loaded 482 isLoading = true; 483 changeCSS(loadingIcon, 'opacity:.4;'); 484 container[appendEl](loadingIcon); 485 preloadedImages[galleryPosition].onload = function () { 486 galleryOpen && changeGalleryImage(movement); 487 }; 488 // if error, store error object in el array 489 preloadedImages[galleryPosition].onerror = function () { 490 galleryEls[galleryPosition] = { 491 error: 'Error loading image', 492 }; 493 galleryOpen && changeGalleryImage(movement); 494 }; 495 } 496 497 function changeGalleryImage(movement) { 498 if (isLoading) { 499 container[removeEl](loadingIcon); 500 isLoading = false; 501 } 502 var activeEl = galleryEls[galleryPosition]; 503 if (activeEl.error) { 504 // show alert if error 505 alert(activeEl.error); 506 } else { 507 // add new image, animate images in and out w/ css animation 508 var oldimg = container.querySelector('img:last-of-type'); 509 displayImage = displayElement = preloadedImages[galleryPosition]; 510 changeCSS( 511 displayImage, 512 ("animation:" + (movement > 0 ? 'bpfl' : 'bpfr') + " .35s;transition:transform .35s") 513 ); 514 changeCSS(oldimg, ("animation:" + (movement > 0 ? 'bpfol' : 'bpfor') + " .35s both")); 515 container[appendEl](displayImage); 516 // update el for closing animation 517 if (activeEl.el) { 518 el = activeEl.el; 519 } 520 } 521 // update counter 522 galleryCounter.innerHTML = (galleryPosition + 1) + "/" + (galleryEls.length); 523 // show / hide caption 524 toggleCaption(galleryEls[galleryPosition].caption); 525 // execute onChangeImage callback 526 onChangeImage && onChangeImage([displayImage, galleryEls[galleryPosition]]); 527 } 528 529 // create video iframe 530 function createIframe() { 531 var url; 532 var prefix = 'https://'; 533 var suffix = 'autoplay=1'; 534 535 // create appropriate url 536 if (opts.ytSrc) { 537 url = prefix + "www.youtube" + (opts.ytNoCookie ? '-nocookie' : '') + ".com/embed/" + siteVidID + "?html5=1&rel=0&playsinline=1&" + suffix; 538 } else if (opts.vimeoSrc) { 539 url = prefix + "player.vimeo.com/video/" + siteVidID + "?" + suffix; 540 } else if (opts.iframeSrc) { 541 url = opts.iframeSrc; 542 } 543 544 // add loading spinner to iframe container 545 changeCSS(loadingIcon, ''); 546 iframeContainer[appendEl](loadingIcon); 547 548 // set iframe src to url 549 iframeSiteVid.src = url; 550 551 update
551IframeDimensions(); 552 553 setTimeout(open, 9); 554 } 555 556 function updateIfram
vendor: 5,462 bytes, lines 556-755
556eDimensions() { 557 var height; 558 var width; 559 560 // handle height / width / aspect / max width for iframe 561 var windowHeight = window.innerHeight * 0.95; 562 var windowWidth = window.innerWidth * 0.95; 563 var windowAspect = windowHeight / windowWidth; 564 565 var ref = opts.dimensions || [1920, 1080]; 566 var dimensionWidth = ref[0]; 567 var dimensionHeight = ref[1]; 568 569 var iframeAspect = dimensionHeight / dimensionWidth; 570 571 if (iframeAspect > windowAspect) { 572 height = Math.min(dimensionHeight, windowHeight); 573 width = height / iframeAspect; 574 } else { 575 width = Math.min(dimensionWidth, windowWidth); 576 height = width * iframeAspect; 577 } 578 579 iframeContainer.style.cssText += "width:" + width + "px;height:" + height + "px;"; 580 } 581 582 // timeout to check video status while loading 583 function checkMedia(errMsg) { 584 if (~[1, 4].indexOf(displayElement.readyState)) { 585 open(); 586 // short timeout to to make sure controls show in safari 11 587 setTimeout(function () { 588 displayElement.play(); 589 }, 99); 590 } else if (displayElement.error) { 591 open(errMsg); 592 } else { 593 checkMediaTimeout = setTimeout(checkMedia, 35, errMsg); 594 } 595 } 596 597 // hide / show loading icon 598 function toggleLoadingIcon(bool) { 599 // don't show loading icon if noLoader is specified 600 if (opts.noLoader) { 601 return 602 } 603 // bool is true if we want to show icon, false if we want to remove 604 // change style to match trigger element dimensions if we want to show 605 bool && 606 changeCSS( 607 loadingIcon, 608 ("top:" + (el.offsetTop) + "px;left:" + (el.offsetLeft) + "px;height:" + (el.clientHeight) + "px;width:" + (el.clientWidth) + "px") 609 ); 610 // add or remove loader from DOM 611 el.parentElement[bool ? appendEl : removeEl](loadingIcon); 612 isLoading = bool; 613 } 614 615 // hide & show caption 616 function toggleCaption(captionContent) { 617 if (captionContent) { 618 captionText.innerHTML = captionContent; 619 } 620 changeCSS( 621 caption, 622 ("opacity:" + (captionContent ? "1;pointer-events:auto" : '0')) 623 ); 624 } 625 626 function addToImgCache(url) { 627 !~imgCache.indexOf(url) && imgCache.push(url); 628 } 629 630 // animate open of image / video; display caption if needed 631 function open(err) { 632 // hide loading spinner 633 isLoading && toggleLoadingIcon(); 634 635 // execute animationStart callback 636 animationStart && animationStart(); 637 638 // check if we have an error string instead of normal event 639 if (typeof err === 'string') { 640 removeContainer(); 641 return opts.onError 642 ? opts.onError() 643 : alert(("Error: The requested " + err + " could not be loaded.")) 644 } 645 646 // if remote image is loaded, add url to imgCache array 647 remoteImage && addToImgCache(imgSrc); 648 649 // transform displayEl to match trigger el 650 displayElement.style.cssText += getRect(); 651 652 // fade in container 653 changeCSS(container, "opacity:1;pointer-events:auto"); 654 655 // set animationEnd callback to run after animation ends (cleared if container closed) 656 if (animationEnd) { 657 animationEnd = setTimeout(animationEnd, 410); 658 } 659 660 isOpen = true; 661 662 galleryOpen = !!galleryEls; 663 664 // enlarge displayEl, fade in caption if hasCaption 665 setTimeout(function () { 666 displayElement.style.cssText += 'transition:transform .35s;transform:none'; 667 captionContent && setTimeout(toggleCaption, 250, captionContent); 668 }, 60); 669 } 670 671 // close active display element 672 function close(e) { 673 var target = e ? e.target : container; 674 var clickEls = [ 675 caption, 676 captionHideButton, 677 displayVideo, 678 displayAudio, 679 captionText, 680 leftArrowBtn, 681 rightArrowBtn, 682 loadingIcon ]; 683 684 // blur to hide close button focus style 685 target.blur(); 686 687 // don't close if one of the clickEls was clicked or container is already closing 688 if (isClosing || ~clickEls.indexOf(target)) { 689 return 690 } 691 692 // animate closing 693 displayElement.style.cssText += getRect(); 694 changeCSS(container, 'pointer-events:auto'); 695 696 // timeout to remove els from dom; use variable to avoid calling more than once 697 setTimeout(removeContainer, 350); 698 699 // clear animationEnd timeout 700 clearTimeout(animationEnd); 701 702 isOpen = false; 703 isClosing = true; 704 } 705 706 // remove container / display element from the DOM 707 function removeContainer() { 708 // clear src of displayElement (or iframe if display el is iframe container) 709 // needs to be done before removing container in IE 710 var srcEl = 711 displayElement === iframeContainer ? iframeSiteVid : displayElement; 712 srcEl.removeAttribute('src'); 713 714 // remove container from DOM & clear inline style 715 document.body[removeEl](container); 716 container[removeEl](displayElement); 717 changeCSS(container, ''); 718 changeCSS(displayElement, ''); 719 720 // remove caption 721 toggleCaption(false); 722 723 if (galleryOpen) { 724 // remove all gallery stuff 725 var images = container.querySelectorAll('img'); 726 for (var i = 0; i < images.length; i++) { 727 container[removeEl](images[i]); 728 } 729 isLoading && container[removeEl](loadingIcon); 730 container[removeEl](galleryCounter); 731 galleryOpen = galleryEls = false; 732 preloadedImages = {}; 733 supportsTouch || container[removeEl](rightArrowBtn); 734 supportsTouch || container[removeEl](leftArrowBtn); 735 // in case displayimage changed, we need to update event listeners 736 displayImage.onload = open; 737 displayImage.onerror = open.bind(null, 'image'); 738 } 739 740 // run close callback 741 opts.onClose && opts.onClose(); 742 743 isClosing = isLoading = false; 744 } 745 746 // style helper functions 747 function changeCSS(ref, newStyle) { 748 var style = ref.style; 749 750 style.cssText = newStyle; 751 } 752 753 return BigPicture; 754 755}());
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.