PageSourceSearch

https://www.miguss.de/js/vendor/baguetteBox.js

js miguss.de collected 2026-10-07 20:43:32 UTC 27,894 bytes, 793 lines download raw bytes

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

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.