vendor: 5,528 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; 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 swipe listeners 228 if ('ontouchstart' in window) { 229 supportsTouch = true; 230 container.ontouchstart = function (ref) { 231 var changedTouches = ref.changedTouches; 232 233 startX = changedTouches[0].pageX; 234 }; 235 container.ontouchmove = function (e) { 236 e.preventDefault(); 237 }; 238 container.ontouchend = function (ref) { 239 var changedTouches = ref.changedTouches; 240 241 if (!galleryOpen) { 242 return 243 } 244 var distX = changedTouches[0].pageX - startX; 245 // swipe right 246 distX < -30 && updateGallery(1); 247 // swipe left 248 distX > 30 && updateGallery(-1); 249 }; 250 } 251 252 // create display image element 253 displayImage = document[createEl]('IMG'); 254 255 // create display video element 256 displayVideo = document[createEl]('VIDEO'); 257 displayVideo.id = 'bp_vid'; 258 displayVideo.setAttribute('playsinline', true); 259 displayVideo.controls = true; 260 displayVideo.loop = true; 261 262 // create audio element 263 displayAudio = document[createEl]('audio'); 264 displayAudio.id = 'bp_aud'; 265 displayAudio.controls = true; 266 displayAudio.loop = true; 267 268 // create gallery counter 269 galleryCounter = document[createEl]('span'); 270 galleryCounter.id = 'bp_count'; 271 272 // create caption elements 273 caption = document[createEl]('DIV'); 274 caption.id = 'bp_caption'; 275 captionHideButton = createCloseButton('bp-xc'); 276 captionHideButton.onclick = toggleCaption.bind(null, false); 277 caption[appendEl](captionHideButton); 278 captionText = document[createEl]('SPAN'); 279 caption[appendEl](captionText); 280 container[appendEl](caption); 281 282 // left / right arrow icons 283 rightArrowBtn = createArrowSymbol(1, 'transform:scalex(-1)'); 284 leftArrowBtn = createArrowSymbol(-1, 'left:0;right:auto'); 285 286 // create loading icon element 287 loadingIcon = document[createEl]('DIV'); 288 loadingIcon.id = 'bp_loader'; 289 loadingIcon.innerHTML =
vendor: 1,162 bytes, lines 290-314
290 '<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>'; 291 // create youtube / vimeo container 292 iframeContainer = document[createEl]('DIV'); 293 iframeContainer.id = 'bp_sv'; 294 295 // create iframe to hold youtube / vimeo player 296 iframeSiteVid = document[createEl]('IFRAME'); 297 iframeSiteVid.setAttribute('allowfullscreen', true); 298 iframeSiteVid.allow = 'autoplay; fullscreen'; 299 iframeSiteVid.onload = function () { return iframeContainer[removeEl](loadingIcon); }; 300 changeCSS( 301 iframeSiteVid, 302 'border:0;position:absolute;height:100%;width:100%;left:0;top:0' 303 ); 304 iframeContainer[appendEl](iframeSiteVid); 305 306 // display image bindings for image load and error 307 displayImage.onload = open; 308 displayImage.onerror = open.bind(null, 'image'); 309 310 window.addEventListener('resize', function () { 311 // adjust loader position on window resize 312 galleryOpen || (isLoading && toggleLoadingIcon(true)); 313 // adjust iframe dimensions 314 displayElement === iframeContainer && updateIfram
vendor: 7,431 bytes, lines 314-553
314eDimensions(); 315 }); 316 317 // close container on escape key press and arrow buttons for gallery 318 document.addEventListener('keyup', function (ref) { 319 var keyCode = ref.keyCode; 320 321 keyCode === 27 && isOpen && close(); 322 if (galleryOpen) { 323 keyCode === 39 && updateGallery(1); 324 keyCode === 37 && updateGallery(-1); 325 keyCode === 38 && updateGallery(10); 326 keyCode === 40 && updateGallery(-10); 327 } 328 }); 329 // prevent scrolling with arrow keys if gallery open 330 document.addEventListener('keydown', function (e) { 331 var usedKeys = [37, 38, 39, 40]; 332 if (galleryOpen && ~usedKeys.indexOf(e.keyCode)) { 333 e.preventDefault(); 334 } 335 }); 336 337 // trap focus within conainer while open 338 document.addEventListener( 339 'focus', 340 function (e) { 341 if (isOpen && !container.contains(e.target)) { 342 e.stopPropagation(); 343 closeButton.focus(); 344 } 345 }, 346 true 347 ); 348 349 // all done 350 initialized = true; 351 } 352 353 // return transform style to make full size display el match trigger el size 354 function getRect() { 355 var ref = el.getBoundingClientRect(); 356 var top = ref.top; 357 var left = ref.left; 358 var width = ref.width; 359 var height = ref.height; 360 var leftOffset = left - (container.clientWidth - width) / 2; 361 var centerTop = top - (container.clientHeight - height) / 2; 362 var scaleWidth = el.clientWidth / displayElement.clientWidth; 363 var scaleHeight = el.clientHeight / displayElement.clientHeight; 364 return ("transform:translate3D(" + leftOffset + "px, " + centerTop + "px, 0) scale3D(" + scaleWidth + ", " + scaleHeight + ", 0)") 365 } 366 367 function makeVidSrc(source) { 368 if (Array.isArray(source)) { 369 displayElement = displayVideo.cloneNode(); 370 source.forEach(function (src) { 371 var source = document[createEl]('SOURCE'); 372 source.src = src; 373 source.type = "video/" + (src.match(/.(\w+)$/)[1]); 374 displayElement[appendEl](source); 375 }); 376 } else { 377 displayElement = displayVideo; 378 displayElement.src = source; 379 } 380 } 381 382 function makeGallery(gallery, position) { 383 var galleryAttribute = opts.galleryAttribute || 'data-bp'; 384 if (Array.isArray(gallery)) { 385 // is array of images 386 galleryPosition = position || 0; 387 galleryEls = gallery; 388 captionContent = gallery[galleryPosition].caption; 389 } else { 390 // is element selector or nodelist 391 galleryEls = [].slice.call( 392 typeof gallery === 'string' 393 ? document.querySelectorAll((gallery + " [" + galleryAttribute + "]")) 394 : gallery 395 ); 396 // find initial gallery position 397 var elIndex = galleryEls.indexOf(el); 398 galleryPosition = 399 position === 0 || position ? position : elIndex !== -1 ? elIndex : 0; 400 // make gallery object w/ els / src / caption 401 galleryEls = galleryEls.map(function (el) { return ({ 402 el: el, 403 src: el.getAttribute(galleryAttribute), 404 caption: el.getAttribute('data-caption'), 405 }); }); 406 } 407 // show loading icon if needed 408 remoteImage = true; 409 // set initial src to imgSrc so it will be cached in open func 410 imgSrc = galleryEls[galleryPosition].src; 411 !~imgCache.indexOf(imgSrc) && toggleLoadingIcon(true); 412 if (galleryEls.length > 1) { 413 // if length is greater than one, add gallery stuff 414 container[appendEl](galleryCounter); 415 galleryCounter.innerHTML = (galleryPosition + 1) + "/" + (galleryEls.length); 416 if (!supportsTouch) { 417 // add arrows if device doesn't support touch 418 container[appendEl](rightArrowBtn); 419 container[appendEl](leftArrowBtn); 420 } 421 } else { 422 // gallery is one, just show without clutter 423 galleryEls = false; 424 } 425 displayElement = displayImage; 426 // set initial image src 427 displayElement.src = imgSrc; 428 } 429 430 function updateGallery(movement) { 431 var galleryLength = galleryEls.length - 1; 432 433 // only allow one change at a time 434 if (isLoading) { 435 return 436 } 437 438 // return if requesting out of range image 439 var isEnd = 440 (movement > 0 && galleryPosition === galleryLength) || 441 (movement < 0 && !galleryPosition); 442 if (isEnd) { 443 // if beginning or end of gallery, run end animation 444 if (!opts.loop) { 445 changeCSS(displayImage, ''); 446 setTimeout( 447 changeCSS, 448 9, 449 displayImage, 450 ("animation:" + (movement > 0 ? 'bpl' : 'bpf') + " .3s;transition:transform .35s") 451 ); 452 return 453 } 454 // if gallery is looped, adjust position to beginning / end 455 galleryPosition = movement > 0 ? -1 : galleryLength + 1; 456 } 457 458 // normalize position 459 galleryPosition = Math.max( 460 0, 461 Math.min(galleryPosition + movement, galleryLength) 462 ) 463 464 // load images before and after for quicker scrolling through pictures 465 ;[galleryPosition - 1, galleryPosition, galleryPosition + 1].forEach( 466 function (position) { 467 // normalize position 468 position = Math.max(0, Math.min(position, galleryLength)); 469 // cancel if image has already been preloaded 470 if (preloadedImages[position]) { return } 471 var src = galleryEls[position].src; 472 // create image for preloadedImages 473 var img = document[createEl]('IMG'); 474 img.addEventListener('load', addToImgCache.bind(null, src)); 475 img.src = src; 476 preloadedImages[position] = img; 477 } 478 ); 479 // if image is loaded, show it 480 if (preloadedImages[galleryPosition].complete) { 481 return changeGalleryImage(movement) 482 } 483 // if not, show loading icon and change when loaded 484 isLoading = true; 485 changeCSS(loadingIcon, 'opacity:.4;'); 486 container[appendEl](loadingIcon); 487 preloadedImages[galleryPosition].onload = function () { 488 galleryOpen && changeGalleryImage(movement); 489 }; 490 // if error, store error object in el array 491 preloadedImages[galleryPosition].onerror = function () { 492 galleryEls[galleryPosition] = { 493 error: 'Error loading image', 494 }; 495 galleryOpen && changeGalleryImage(movement); 496 }; 497 } 498 499 function changeGalleryImage(movement) { 500 if (isLoading) { 501 container[removeEl](loadingIcon); 502 isLoading = false; 503 } 504 var activeEl = galleryEls[galleryPosition]; 505 if (activeEl.error) { 506 // show alert if error 507 alert(activeEl.error); 508 } else { 509 // add new image, animate images in and out w/ css animation 510 var oldimg = container.querySelector('img:last-of-type'); 511 displayImage = displayElement = preloadedImages[galleryPosition]; 512 changeCSS( 513 displayImage, 514 ("animation:" + (movement > 0 ? 'bpfl' : 'bpfr') + " .35s;transition:transform .35s") 515 ); 516 changeCSS(oldimg, ("animation:" + (movement > 0 ? 'bpfol' : 'bpfor') + " .35s both")); 517 container[appendEl](displayImage); 518 // update el for closing animation 519 if (activeEl.el) { 520 el = activeEl.el; 521 } 522 } 523 // update counter 524 galleryCounter.innerHTML = (galleryPosition + 1) + "/" + (galleryEls.length); 525 // show / hide caption 526 toggleCaption(galleryEls[galleryPosition].caption); 527 // execute onChangeImage callback 528 onChangeImage && onChangeImage([displayImage, galleryEls[galleryPosition]]); 529 } 530 531 // create video iframe 532 function createIframe() { 533 var url; 534 var prefix = 'https://'; 535 var suffix = 'autoplay=1'; 536 537 // create appropriate url 538 if (opts.ytSrc) { 539 url = prefix + "www.youtube" + (opts.ytNoCookie ? '-nocookie' : '') + ".com/embed/" + siteVidID + "?html5=1&rel=0&playsinline=1&" + suffix; 540 } else if (opts.vimeoSrc) { 541 url = prefix + "player.vimeo.com/video/" + siteVidID + "?" + suffix; 542 } else if (opts.iframeSrc) { 543 url = opts.iframeSrc; 544 } 545 546 // add loading spinner to iframe container 547 changeCSS(loadingIcon, ''); 548 iframeContainer[appendEl](loadingIcon); 549 550 // set iframe src to url 551 iframeSiteVid.src = url; 552 553 update
553IframeDimensions(); 554 555 setTimeout(open, 9); 556 } 557 558 function updateIfram
vendor: 5,462 bytes, lines 558-757
558eDimensions() { 559 var height; 560 var width; 561 562 // handle height / width / aspect / max width for iframe 563 var windowHeight = window.innerHeight * 0.95; 564 var windowWidth = window.innerWidth * 0.95; 565 var windowAspect = windowHeight / windowWidth; 566 567 var ref = opts.dimensions || [1920, 1080]; 568 var dimensionWidth = ref[0]; 569 var dimensionHeight = ref[1]; 570 571 var iframeAspect = dimensionHeight / dimensionWidth; 572 573 if (iframeAspect > windowAspect) { 574 height = Math.min(dimensionHeight, windowHeight); 575 width = height / iframeAspect; 576 } else { 577 width = Math.min(dimensionWidth, windowWidth); 578 height = width * iframeAspect; 579 } 580 581 iframeContainer.style.cssText += "width:" + width + "px;height:" + height + "px;"; 582 } 583 584 // timeout to check video status while loading 585 function checkMedia(errMsg) { 586 if (~[1, 4].indexOf(displayElement.readyState)) { 587 open(); 588 // short timeout to to make sure controls show in safari 11 589 setTimeout(function () { 590 displayElement.play(); 591 }, 99); 592 } else if (displayElement.error) { 593 open(errMsg); 594 } else { 595 checkMediaTimeout = setTimeout(checkMedia, 35, errMsg); 596 } 597 } 598 599 // hide / show loading icon 600 function toggleLoadingIcon(bool) { 601 // don't show loading icon if noLoader is specified 602 if (opts.noLoader) { 603 return 604 } 605 // bool is true if we want to show icon, false if we want to remove 606 // change style to match trigger element dimensions if we want to show 607 bool && 608 changeCSS( 609 loadingIcon, 610 ("top:" + (el.offsetTop) + "px;left:" + (el.offsetLeft) + "px;height:" + (el.clientHeight) + "px;width:" + (el.clientWidth) + "px") 611 ); 612 // add or remove loader from DOM 613 el.parentElement[bool ? appendEl : removeEl](loadingIcon); 614 isLoading = bool; 615 } 616 617 // hide & show caption 618 function toggleCaption(captionContent) { 619 if (captionContent) { 620 captionText.innerHTML = captionContent; 621 } 622 changeCSS( 623 caption, 624 ("opacity:" + (captionContent ? "1;pointer-events:auto" : '0')) 625 ); 626 } 627 628 function addToImgCache(url) { 629 !~imgCache.indexOf(url) && imgCache.push(url); 630 } 631 632 // animate open of image / video; display caption if needed 633 function open(err) { 634 // hide loading spinner 635 isLoading && toggleLoadingIcon(); 636 637 // execute animationStart callback 638 animationStart && animationStart(); 639 640 // check if we have an error string instead of normal event 641 if (typeof err === 'string') { 642 removeContainer(); 643 return opts.onError 644 ? opts.onError() 645 : alert(("Error: The requested " + err + " could not be loaded.")) 646 } 647 648 // if remote image is loaded, add url to imgCache array 649 remoteImage && addToImgCache(imgSrc); 650 651 // transform displayEl to match trigger el 652 displayElement.style.cssText += getRect(); 653 654 // fade in container 655 changeCSS(container, "opacity:1;pointer-events:auto"); 656 657 // set animationEnd callback to run after animation ends (cleared if container closed) 658 if (animationEnd) { 659 animationEnd = setTimeout(animationEnd, 410); 660 } 661 662 isOpen = true; 663 664 galleryOpen = !!galleryEls; 665 666 // enlarge displayEl, fade in caption if hasCaption 667 setTimeout(function () { 668 displayElement.style.cssText += 'transition:transform .35s;transform:none'; 669 captionContent && setTimeout(toggleCaption, 250, captionContent); 670 }, 60); 671 } 672 673 // close active display element 674 function close(e) { 675 var target = e ? e.target : container; 676 var clickEls = [ 677 caption, 678 captionHideButton, 679 displayVideo, 680 displayAudio, 681 captionText, 682 leftArrowBtn, 683 rightArrowBtn, 684 loadingIcon ]; 685 686 // blur to hide close button focus style 687 target.blur(); 688 689 // don't close if one of the clickEls was clicked or container is already closing 690 if (isClosing || ~clickEls.indexOf(target)) { 691 return 692 } 693 694 // animate closing 695 displayElement.style.cssText += getRect(); 696 changeCSS(container, 'pointer-events:auto'); 697 698 // timeout to remove els from dom; use variable to avoid calling more than once 699 setTimeout(removeContainer, 350); 700 701 // clear animationEnd timeout 702 clearTimeout(animationEnd); 703 704 isOpen = false; 705 isClosing = true; 706 } 707 708 // remove container / display element from the DOM 709 function removeContainer() { 710 // clear src of displayElement (or iframe if display el is iframe container) 711 // needs to be done before removing container in IE 712 var srcEl = 713 displayElement === iframeContainer ? iframeSiteVid : displayElement; 714 srcEl.removeAttribute('src'); 715 716 // remove container from DOM & clear inline style 717 document.body[removeEl](container); 718 container[removeEl](displayElement); 719 changeCSS(container, ''); 720 changeCSS(displayElement, ''); 721 722 // remove caption 723 toggleCaption(false); 724 725 if (galleryOpen) { 726 // remove all gallery stuff 727 var images = container.querySelectorAll('img'); 728 for (var i = 0; i < images.length; i++) { 729 container[removeEl](images[i]); 730 } 731 isLoading && container[removeEl](loadingIcon); 732 container[removeEl](galleryCounter); 733 galleryOpen = galleryEls = false; 734 preloadedImages = {}; 735 supportsTouch || container[removeEl](rightArrowBtn); 736 supportsTouch || container[removeEl](leftArrowBtn); 737 // in case displayimage changed, we need to update event listeners 738 displayImage.onload = open; 739 displayImage.onerror = open.bind(null, 'image'); 740 } 741 742 // run close callback 743 opts.onClose && opts.onClose(); 744 745 isClosing = isLoading = false; 746 } 747 748 // style helper functions 749 function changeCSS(ref, newStyle) { 750 var style = ref.style; 751 752 style.cssText = newStyle; 753 } 754 755 return BigPicture; 756 757}());
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.