1/*! 2 * baguetteBox.js 3 * @author feimosi 4 * @version %%INJECT_VERSION%% 5 * @url https://github.com/feimosi/baguetteBox.js 6 */ 7 8/* global define, module */ 9 10(function (root, factory) { 11 'use strict'; 12 if (typeof define === 'function' && define.amd) { 13 define(factory); 14 } else if (typeof exports === 'object') { 15 module.exports = factory(); 16 } else { 17 root.baguetteBox = factory(); 18 } 19}(this, function () { 20 'use strict'; 21 22 // SVG shapes used on the buttons 23 var leftArrow = '<svg width="44" height="60">' + 24 '<polyline points="30 10 10 30 30 50" stroke="rgba(255,255,255,0.8)" stroke-width="2"' + 25 'stroke-linecap="butt" fill="none" stroke-linejoin="round"/>' + 26 '</svg>', 27 rightArrow = '<svg width="44" height="60">' + 28 '<polyline points="14 10 34 30 14 50" stroke="rgba(255,255,255,0.8)" stroke-width="2"' + 29 'stroke-linecap="butt" fill="none" stroke-linejoin="round"/>' + 30 '</svg>', 31 closeX = '<svg width="30" height="30">' + 32 '<g stroke="rgba(255,255,255,0.8)" stroke-width="2">' + 33 '<line x1="5" y1="5" x2="25" y2="25"/>' + 34 '<line x1="5" y1="25" x2="25" y2="5"/>' + 35 '</g></svg>'; 36 // Global options and their defaults 37 var options = {}, 38 defaults = { 39 captions: true, 40 buttons: 'auto', 41 fullScreen: false, 42 noScrollbars: false, 43 bodyClass: 'baguetteBox-open', 44 titleTag: false, 45 async: false, 46 preload: 2, 47 animation: 'slideIn', 48 afterShow: null, 49 afterHide: null, 50 onChange: null, 51 overlayBackgroundColor: 'rgba(0,0,0,.8)' 52 }; 53 // Object containing information about features compatibility 54 var supports = {}; 55 // DOM Elements references 56 var overlay, slider, previousButton, nextButton, closeButton; 57 // An array with all images in the current gallery 58 var currentGallery = []; 59 // Current image index inside the slider 60 var currentIndex = 0; 61 // Visibility of the overlay 62 var isOverlayVisible = false; 63 // Touch event start position (for slide gesture) 64 var touch = {}; 65 // If set to true ignore touch events because animation was already fired 66 var touchFlag = false; 67 // Regex pattern to match image files 68 var regex = /.+\.(gif|jpe?g|png|webp)/i; 69 // Object of all used galleries 70 var data = {}; 71 // Array containing temporary images DOM elements 72 var imagesElements = []; 73 // The last focused element before opening the overlay 74 //var documentLastFocus = null; 75 var overlayClickHandler = function (event) { 76 // Close the overlay when user clicks directly on the background 77 if (event.target.id.indexOf('baguette-img') !== -1) { 78 hideOverlay(); 79 } 80 }; 81 var previousButtonClickHandler = function (event) { 82 event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; // eslint-disable-line no-unused-expressions 83 showPreviousImage(); 84 }; 85 var nextButtonClickHandler = function (event) { 86 event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; // eslint-disable-line no-unused-expressions 87 showNextImage(); 88 }; 89 var closeButtonClickHandler = function (event) { 90 event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; // eslint-disable-line no-unused-expressions 91 hideOverlay(); 92 }; 93 var touchstartHandler = function (event) { 94 touch.count++; 95 if (touch.count > 1) { 96 touch.multitouch = true; 97 } 98 // Save x and y axis position 99 touch.startX = event.changedTouches[0].pageX; 100 touch.startY = event.changedTouches[0].pageY; 101 }; 102 var touchmoveHandler = function (event) { 103 // If action was already triggered or multitouch return 104 if (touchFlag || touch.multitouch) { 105 return; 106 } 107 //event.preventDefault ? event.preventDefault() : event.returnValue = false; // eslint-disable-line no-unused-expressions 108 var touchEvent = event.touches[0] || event.changedTouches[0]; 109 console.log(touchEvent.pageX - touch.startX); 110 // Move at least 40 pixels to trigger the action 111 if (touchEvent.pageX - touch.startX > 1) { 112 touchFlag = true; 113 showPreviousImage(); 114 } else if (touchEvent.pageX - touch.startX < -1) { 115 touchFlag = true; 116 showNextImage(); 117 // Move 100 pixels up to close the overlay 118 } //else if (touch.startY - touchEvent.pageY > 10) { 119 // hideOverlay(); 120 // } 121 }; 122 var touchendHandler = function () { 123 touch.count--; 124 if (touch.count <= 0) { 125 touch.multitouch = false;
126 } 127 touchFlag = false; 128 }; 129 var contextmenuHandler = function () { 130 touchendHandler(); 131 }; 132 133 var trapFocusInsideOverlay = function (event) { 134 if (overlay.style.display === 'block' && (overlay.contains && !overlay.contains(event.target))) { 135 event.stopPropagation(); 136 initFocus(); 137 } 138 }; 139 140 // forEach polyfill for IE8 141 // http://stackoverflow.com/a/14827443/1077846 142 /* eslint-disable */ 143 if (![].forEach) { 144 Array.prototype.forEach = function (callback, thisArg) { 145 for (var i = 0; i < this.length; i++) { 146 callback.call(thisArg, this[i], i, this); 147 } 148 }; 149 } 150 151 // filter polyfill for IE8 152 // https://gist.github.com/eliperelman/1031656 153 if (![].filter) { 154 Array.prototype.filter = function (a, b, c, d, e) { 155 c = this; 156 d = []; 157 for (e = 0; e < c.length; e++) 158 a.call(b, c[e], e, c) && d.push(c[e]); 159 return d; 160 }; 161 } 162 /* eslint-enable */ 163 164 // Script entry point 165 function run(selector, userOptions) { 166 // Fill supports object 167 supports.transforms = testTransformsSupport(); 168 supports.svg = testSvgSupport(); 169 supports.passiveEvents = testPassiveEventsSupport(); 170 171 buildOverlay(); 172 removeFromCache(selector); 173 return bindImageClickListeners(selector, userOptions); 174 } 175 176 function bindImageClickListeners(selector, userOptions) { 177 // For each gallery bind a click event to every image inside it 178 var galleryNodeList = document.querySelectorAll(selector); 179 var selectorData = { 180 galleries: [], 181 nodeList: galleryNodeList 182 }; 183 data[selector] = selectorData; 184 185 [].forEach.call(galleryNodeList, function (galleryElement) { 186 if (userOptions && userOptions.filter) { 187 regex = userOptions.filter; 188 } 189 190 // Get nodes from gallery elements or single-element galleries 191 var tagsNodeList = []; 192 if (galleryElement.tagName === 'A') { 193 tagsNodeList = [galleryElement]; 194 } else { 195 tagsNodeList = galleryElement.getElementsByTagName('a'); 196 } 197 198 // Filter 'a' elements from those not linking to images 199 tagsNodeList = [].filter.call(tagsNodeList, function (element) { 200 if (element.className.indexOf(userOptions && userOptions.ignoreClass) === -1) { 201 return regex.test(element.href); 202 } 203 }); 204 if (tagsNodeList.length === 0) { 205 return; 206 } 207 208 var gallery = []; 209 [].forEach.call(tagsNodeList, function (imageElement, imageIndex) { 210 var imageElementClickHandler = function (event) { 211 event.preventDefault ? event.preventDefault() : event.returnValue = false; // eslint-disable-line no-unused-expressions 212 prepareOverlay(gallery, userOptions); 213 showOverlay(imageIndex); 214 }; 215 var imageItem = { 216 eventHandler: imageElementClickHandler, 217 imageElement: imageElement 218 }; 219 bind(imageElement, 'click', imageElementClickHandler); 220 gallery.push(imageItem); 221 }); 222 selectorData.galleries.push(gallery); 223 }); 224 225 return selectorData.galleries; 226 } 227 228 function clearCachedData() { 229 for (var selector in data) { 230 if (data.hasOwnProperty(selector)) { 231 removeFromCache(selector); 232 } 233 } 234 } 235 236 function removeFromCache(selector) { 237 if (!data.hasOwnProperty(selector)) { 238 return; 239 } 240 var galleries = data[selector].galleries; 241 [].forEach.call(galleries, function (gallery) { 242 [].forEach.call(gallery, function (imageItem) { 243 unbind(imageItem.imageElement, 'click', imageItem.eventHandler); 244 }); 245 246 if (currentGallery === gallery) { 247 currentGallery = []; 248 } 249 }); 250 251 delete data[selector]; 252 } 253 254 function buildOverlay() {
255 overlay = getByID('baguetteBox-overlay'); 256 // Check if the overlay already exists 257 if (overlay) { 258 slider = getByID('baguetteBox-slider'); 259 previousButton = getByID('previous-button'); 260 nextButton = getByID('next-button'); 261 closeButton = getByID('close-button'); 262 return; 263 } 264 // Create overlay element 265 overlay = create('div'); 266 overlay.setAttribute('role', 'dialog'); 267 overlay.id = 'baguetteBox-overlay'; 268 document.getElementsByTagName('body')[0].appendChild(overlay); 269 // Create gallery slider element 270 slider = create('div'); 271 slider.id = 'baguetteBox-slider'; 272 overlay.appendChild(slider); 273 // Create all necessary buttons 274 previousButton = create('button'); 275 previousButton.setAttribute('type', 'button'); 276 previousButton.id = 'previous-button'; 277 previousButton.setAttribute('aria-label', 'Previous'); 278 previousButton.innerHTML = supports.svg ? leftArrow : '<'; 279 overlay.appendChild(previousButton); 280 281 nextButton = create('button'); 282 nextButton.setAttribute('type', 'button'); 283 nextButton.id = 'next-button'; 284 nextButton.setAttribute('aria-label', 'Next'); 285 nextButton.innerHTML = supports.svg ? rightArrow : '>'; 286 overlay.appendChild(nextButton); 287 288 closeButton = create('button'); 289 closeButton.setAttribute('type', 'button'); 290 closeButton.id = 'close-button'; 291 closeButton.setAttribute('aria-label', 'Close'); 292 closeButton.innerHTML = supports.svg ? closeX : '×'; 293 overlay.appendChild(closeButton); 294 295 previousButton.className = nextButton.className = closeButton.className = 'baguetteBox-button'; 296 297 bindEvents(); 298 } 299 300 function keyDownHandler(event) { 301 switch (event.keyCode) { 302 case 37: // Left arrow 303 showPreviousImage(); 304 break; 305 case 39: // Right arrow 306 showNextImage(); 307 break; 308 case 27: // Esc 309 hideOverlay(); 310 break; 311 case 36: // Home 312 showFirstImage(event); 313 break; 314 case 35: // End 315 showLastImage(event); 316 break; 317 } 318 } 319 320 function bindEvents() { 321 var options = supports.passiveEvents ? { passive: true } : null; 322 bind(overlay, 'click', overlayClickHandler); 323 bind(previousButton, 'click', previousButtonClickHandler); 324 bind(nextButton, 'click', nextButtonClickHandler); 325 bind(closeButton, 'click', closeButtonClickHandler); 326 bind(slider, 'contextmenu', contextmenuHandler); 327 bind(overlay, 'touchstart', touchstartHandler, options); 328 bind(overlay, 'touchmove', touchmoveHandler, options); 329 bind(overlay, 'touchend', touchendHandler); 330 bind(document, 'focus', trapFocusInsideOverlay, true); 331 } 332 333 function unbindEvents() { 334 var options = supports.passiveEvents ? { passive: true } : null; 335 unbind(overlay, 'click', overlayClickHandler); 336 unbind(previousButton, 'click', previousButtonClickHandler); 337 unbind(nextButton, 'click', nextButtonClickHandler); 338 unbind(closeButton, 'click', closeButtonClickHandler); 339 unbind(slider, 'contextmenu', contextmenuHandler); 340 unbind(overlay, 'touchstart', touchstartHandler, options); 341 unbind(overlay, 'touchmove', touchmoveHandler, options); 342 unbind(overlay, 'touchend', touchendHandler); 343 unbind(document, 'focus', trapFocusInsideOverlay, true); 344 } 345 346 function prepareOverlay(gallery, userOptions) { 347 // If the same gallery is being opened prevent from loading it once again 348 if (currentGallery === gallery) { 349 return; 350 } 351 currentGallery = gallery; 352 // Update gallery specific options 353 setOptions(userOptions); 354 // Empty slider of previous contents (more effective than .innerHTML = "") 355 while (slider.firstChild) { 356 slider.removeChild(slider.firstChild); 357 } 358 imagesElements.length = 0; 359 360 var imagesFiguresIds = []; 361 var imagesCaptionsIds = []; 362 // Prepare and append images containers and populate figure and captions IDs arrays 363 for (var i = 0, fullImage; i < gallery.length; i++) { 364 fullImage = create('div'); 365 fullImage.className = 'full-image'; 366 fullImage.id = 'baguette-img-' + i; 367 imagesElements.push(fullImage); 368 369 imagesFiguresIds.push('baguetteBox-figure-' + i); 370 imagesCaptionsIds.push('baguetteBox-figcaption-' + i); 371 slider.appendChild(imagesElements[i]); 372 } 373 overlay.setAttribute('aria-labelledby', imagesFiguresIds.join(' ')); 374 overlay.setAttribute('aria-describedby', imagesCaptionsIds.join(' ')); 375 } 376 377 function setOptions(newOptions) { 378 if (!newOptions) { 379 newOptions = {}; 380 } 381 // Fill options object 382 for (var item in defaults) { 383 options[item] = defaults[item]; 384 if (typeof newOptions[item] !== 'undefined') { 385 options[item] = newOptions[item]; 386 } 387 } 388 /* Apply new options */ 389 // Change transition for proper animation 390 slider.style.transition = slider.style.webkitTransition = (options.animation === 'fadeIn' ? 'opacity .4s ease' : 391 options.animation === 'slideIn' ? '' : 'none'); 392 // Hide buttons if necessary 393 if (options.buttons === 'auto' && ('ontouchstart' in window || currentGallery.length === 1)) { 394 options.buttons = false;
395 } 396 // Set buttons style to hide or display them 397 previousButton.style.display = nextButton.style.display = (options.buttons ? '' : 'none'); 398 // Set overlay color 399 try { 400 overlay.style.backgroundColor = options.overlayBackgroundColor; 401 } catch (e) { 402 // Silence the error and continue 403 } 404 } 405 406 function showOverlay(chosenImageIndex) { 407 if (options.noScrollbars) { 408 document.documentElement.style.overflowY = 'hidden'; 409 document.body.style.overflowY = 'scroll'; 410 } 411 if (overlay.style.display === 'block') { 412 return; 413 } 414 415 bind(document, 'keydown', keyDownHandler); 416 currentIndex = chosenImageIndex; 417 touch = { 418 count: 0, 419 startX: null, 420 startY: null 421 }; 422 loadImage(currentIndex, function () { 423 preloadNext(currentIndex); 424 preloadPrev(currentIndex); 425 }); 426 427 updateOffset(); 428 overlay.style.display = 'block'; 429 if (options.fullScreen) { 430 enterFullScreen(); 431 } 432 // Fade in overlay 433 setTimeout(function () { 434 overlay.className = 'visible'; 435 if (options.bodyClass && document.body.classList) { 436 document.body.classList.add(options.bodyClass); 437 } 438 if (options.afterShow) { 439 options.afterShow(); 440 } 441 }, 50); 442 if (options.onChange) { 443 options.onChange(currentIndex, imagesElements.length); 444 } 445 //documentLastFocus = document.activeElement; 446 initFocus(); 447 isOverlayVisible = true; 448 } 449 450 function initFocus() { 451 if (options.buttons) { 452 previousButton.focus(); 453 } else { 454 closeButton.focus(); 455 } 456 } 457 458 function enterFullScreen() { 459 if (overlay.requestFullscreen) { 460 overlay.requestFullscreen(); 461 } else if (overlay.webkitRequestFullscreen) { 462 overlay.webkitRequestFullscreen(); 463 } else if (overlay.mozRequestFullScreen) { 464 overlay.mozRequestFullScreen(); 465 } 466 } 467 468 function exitFullscreen() { 469 if (document.exitFullscreen) { 470 document.exitFullscreen(); 471 } else if (document.mozCancelFullScreen) { 472 document.mozCancelFullScreen(); 473 } else if (document.webkitExitFullscreen) { 474 document.webkitExitFullscreen(); 475 } 476 } 477 478 function hideOverlay() { 479 if (options.noScrollbars) { 480 document.documentElement.style.overflowY = 'auto'; 481 document.body.style.overflowY = 'auto'; 482 } 483 if (overlay.style.display === 'none') { 484 return; 485 } 486 487 unbind(document, 'keydown', keyDownHandler); 488 // Fade out and hide the overlay 489 overlay.className = ''; 490 setTimeout(function () { 491 overlay.style.display = 'none'; 492 if (document.fullscreen) { 493 exitFullscreen(); 494 } 495 if (options.bodyClass && document.body.classList) { 496 document.body.classList.remove(options.bodyClass); 497 } 498 if (options.afterHide) { 499 options.afterHide(); 500 } 501 //documentLastFocus && documentLastFocus.focus(); 502 isOverlayVisible = false; 503 }, 500); 504 } 505 506 function loadImage(index, callback) { 507 var imageContainer = imagesElements[index]; 508 var galleryItem = currentGallery[index]; 509 510 // Return if the index exceeds prepared images in the overlay 511 // or if the current gallery has been changed / closed 512 if (typeof imageContainer === 'undefined' || typeof galleryItem === 'undefined') { 513 return; 514 } 515 516 // If image is already loaded run callback and return 517 if (imageContainer.getElementsByTagName('img')[0]) { 518 if (callback) { 519 callback(); 520 } 521 return; 522 } 523 524 // Get element reference, optional caption and source path 525 var imageElement = galleryItem.imageElement; 526 var thumbnailElement = imageElement.getElementsByTagName('img')[0]; 527 var imageCaption = typeof options.captions === 'function' ? 528 options.captions.call(currentGallery, imageElement) : 529 imageElement.getAttribute('data-caption') || imageElement.title; 530 var imageSrc = getImageSrc(imageElement); 531 532 // Prepare figure element 533 var figure = create('figure'); 534 figure.id = 'baguetteBox-figure-' + index; 535 figure.innerHTML = '<div class="baguetteBox-spinner">' + 536 '<div class="baguetteBox-double-bounce1"></div>' + 537 '<div class="baguetteBox-double-bounce2"></div>' + 538 '</div>'; 539 // Insert caption if available 540 if (options.captions && imageCaption) { 541 var figcaption = create('figcaption'); 542 figcaption.id = 'baguetteBox-figcaption-' + index; 543 figcaption.innerHTML = imageCaption; 544 figure.appendChild(figcaption); 545 } 546 imageContainer.appendChild(figure); 547 548 // Prepare gallery img element 549 var image = create('img'); 550 image.onload = function () { 551 // Remove loader element 552 var spinner = document.querySelector('#baguette-img-' + index + ' .baguetteBox-spinner'); 553 figure.removeChild(spinner); 554 if (!options.async && callback) { 555 callback(); 556 } 557 }; 558 image.setAttribute('src', imageSrc); 559 image.alt = thumbnailElement ? thumbnailElement.alt || '' : ''; 560 if (options.titleTag && imageCaption) { 561 image.title = imageCaption; 562 } 563 figure.appendChild(image); 564 565 // Run callback 566 if (options.async && callback) { 567 callback(); 568 } 569 } 570 571 // Get image source location, mostly used for responsive images 572 function getImageSrc(image) { 573 // Set default image path from href 574 var result = image.href; 575 // If dataset is supported find the most suitable image 576 if (image.dataset) { 577 var srcs = []; 578 // Get all possible image versions depending on the resolution 579 for (var item in image.dataset) { 580 if (item.substring(0, 3) === 'at-' && !isNaN(item.substring(3))) { 581 srcs[item.replace('at-', '')] = image.dataset[item]; 582 } 583 } 584 // Sort resolutions ascending 585 var keys = Object.keys(srcs).sort(function (a, b) { 586 return parseInt(a, 10) < parseInt(b, 10) ? -1 : 1; 587 }); 588 // Get real screen resolution 589 var width = window.innerWidth * window.devicePixelRatio; 590 // Find the first image bigger than or equal to the current width 591 var i = 0;
592 while (i < keys.length - 1 && keys[i] < width) { 593 i++; 594 } 595 result = srcs[keys[i]] || result; 596 } 597 return result; 598 } 599 600 // Return false at the right end of the gallery 601 function showNextImage() { 602 var elmnt = document.getElementById(currentIndex + 1); 603 elmnt.scrollIntoView(); 604 return show(currentIndex + 1); 605 } 606 607 // Return false at the left end of the gallery 608 function showPreviousImage() { 609 if (currentIndex == 0) return false; 610 var elmnt = document.getElementById(currentIndex); 611 elmnt.scrollIntoView(); 612 return show(currentIndex - 1); 613 } 614 615 // Return false at the left end of the gallery 616 function showFirstImage(event) { 617 if (event) { 618 event.preventDefault(); 619 } 620 return show(0); 621 } 622 623 // Return false at the right end of the gallery 624 function showLastImage(event) { 625 if (event) { 626 event.preventDefault(); 627 } 628 return show(currentGallery.length - 1); 629 } 630 631 /** 632 * Move the gallery to a specific index 633 * @param `index` {number} - the position of the image 634 * @param `gallery` {array} - gallery which should be opened, if omitted assumes the currently opened one 635 * @return {boolean} - true on success or false if the index is invalid 636 */ 637 function show(index, gallery) { 638 if (!isOverlayVisible && index >= 0 && index < gallery.length) { 639 prepareOverlay(gallery, options); 640 showOverlay(index); 641 return true; 642 } 643 if (index < 0) { 644 if (options.animation) { 645 bounceAnimation('left'); 646 } 647 return false; 648 } 649 if (index >= imagesElements.length) { 650 console.log('hemos llegado al final'); 651 if (options.animation) { 652 bounceAnimation('right'); 653 } 654 return false; 655 } 656 657 currentIndex = index; 658 loadImage(currentIndex, function () { 659 preloadNext(currentIndex); 660 preloadPrev(currentIndex); 661 }); 662 updateOffset(); 663 664 if (options.onChange) { 665 options.onChange(currentIndex, imagesElements.length); 666 } 667 668 return true; 669 } 670 671 /** 672 * Triggers the bounce animation 673 * @param {('left'|'right')} direction - Direction of the movement 674 */ 675 function bounceAnimation(direction) { 676 slider.className = 'bounce-from-' + direction; 677 setTimeout(function () { 678 slider.className = ''; 679 }, 400); 680 } 681 682 function updateOffset() { 683 var offset = -currentIndex * 100 + '%'; 684 if (options.animation === 'fadeIn') { 685 slider.style.opacity = 0; 686 setTimeout(function () { 687 supports.transforms ? 688 slider.style.transform = slider.style.webkitTransform = 'translate3d(' + offset + ',0,0)' 689 : slider.style.left = offset; 690 slider.style.opacity = 1; 691 }, 400); 692 } else { 693 supports.transforms ? 694 slider.style.transform = slider.style.webkitTransform = 'translate3d(' + offset + ',0,0)' 695 : slider.style.left = offset; 696 } 697 } 698 699 // CSS 3D Transforms test 700 function testTransformsSupport() { 701 var div = create('div'); 702 return typeof div.style.perspective !== 'undefined' || typeof div.style.webkitPerspective !== 'undefined'; 703 } 704 705 // Inline SVG test 706 function testSvgSupport() { 707 var div = create('div'); 708 div.innerHTML = '<svg/>'; 709 return (div.firstChild && div.firstChild.namespaceURI) === 'http://www.w3.org/2000/svg'; 710 } 711 712 // Borrowed from https://github.com/seiyria/bootstrap-slider/pull/680/files 713 /* eslint-disable getter-return */ 714 function testPassiveEventsSupport() { 715 var passiveEvents = false; 716 try { 717 var opts = Object.defineProperty({}, 'passive', { 718 get: function () { 719 passiveEvents = true; 720 } 721 }); 722 window.addEventListener('test', null, opts); 723 } catch (e) { /* Silence the error and continue */ } 724 725 return passiveEvents; 726 } 727 /* eslint-enable getter-return */ 728 729 function preloadNext(index) { 730 if (index - currentIndex >= options.preload) { 731 return; 732 } 733 loadImage(index + 1, function () { 734 preloadNext(index + 1); 735 }); 736 } 737 738 function preloadPrev(index) { 739 if (currentIndex - index >= options.preload) { 740 return; 741 } 742 loadImage(index - 1, function () { 743 preloadPrev(index - 1); 744 }); 745 } 746 747 function bind(element, event, callback, options) { 748 if (element.addEventListener) { 749 element.addEventListener(event, callback, options); 750 } else { 751 // IE8 fallback 752 element.attachEvent('on' + event, function (event) { 753 // `event` and `event.target` are not provided in IE8 754 event = event || window.event; 755 event.target = event.target || event.srcElement; 756 callback(event); 757 }); 758 } 759 } 760 761 function unbind(element, event, callback, options) { 762 if (element.removeEventListener) { 763 element.removeEventListener(event, callback, options); 764 } else { 765 // IE8 fallback 766 element.detachEvent('on' + event, callback); 767 } 768 } 769 770 function getByID(id) { 771 return document.getElementById(id); 772 } 773 774 function create(element) { 775 return document.createElement(element); 776 } 777 778 function destroyPlugin() { 779 unbindEvents(); 780 clearCachedData(); 781 unbind(document, 'keydown', keyDownHandler); 782 document.getElementsByTagName('body')[0].removeChild(document.getElementById('baguetteBox-overlay')); 783 data = {}; 784 currentGallery = []; 785 currentIndex = 0; 786 } 787 788 return { 789 run: run, 790 show: show, 791 showNext: showNextImage, 792 showPrevious: showPreviousImage, 793 hide: hideOverlay, 794 destroy: destroyPlugin 795 }; 796}));
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.