PageSourceSearch

https://markington.n-yorks.sch.uk/service/util/custom/javascript/baguetteBox/baguetteBox-1.1.a.js

js markington.n-yorks.sch.uk collected 2026-10-04 02:09:42 UTC 17,035 bytes, 464 lines download raw bytes

1/*!
2 * baguetteBox.js
3 * @author  feimosi
4 * @version 1.1.1
5 * @url https://github.com/feimosi/baguetteBox.js
6 */
7
8var baguetteBox = (function() {
9    // SVG shapes used within the buttons
10    var leftArrow = '<svg width="44" height="60">' +
11            '<polyline points="30 10 10 30 30 50" stroke="rgba(255,255,255,0.5)" stroke-width="4"' +
12              'stroke-linecap="butt" fill="none" stroke-linejoin="round"/>' +
13            '</svg>',
14        rightArrow = '<svg width="44" height="60">' +
15            '<polyline points="14 10 34 30 14 50" stroke="rgba(255,255,255,0.5)" stroke-width="4"' +
16              'stroke-linecap="butt" fill="none" stroke-linejoin="round"/>' +
17            '</svg>',
18        closeX = '<svg width="30" height="30">' +
19            '<g stroke="rgb(160, 160, 160)" stroke-width="4">' +
20            '<line x1="5" y1="5" x2="25" y2="25"/>' +
21            '<line x1="5" y1="25" x2="25" y2="5"/>' +
22            '</g></svg>';
23    // Global options and their defaults
24    var options = {}, defaults = {
25        captions: true,
26        buttons: 'auto',
27        async: false,
28        preload: 2,
29        animation: 'slideIn',
30        afterShow: null,
31        afterHide: null
32    };
33    // Object containing information about features compatibility
34    var supports = {};
35    // DOM Elements references
36    var overlay, slider, previousButton, nextButton, closeButton;
37    // Current image index inside the slider and displayed gallery index
38    var currentIndex = 0, currentGallery = -1;
39    // Touch event start position (for slide gesture)
40    var touchStartX;
41    // If set to true ignore touch events because animation was already fired
42    var touchFlag = false;
43    // Regex pattern to match image files
44    var regex = /.+\.(gif|jpe?g|png|webp)/i;
45    // Array of all used galleries (DOM elements)
46    var galleries = [];
47    // 2D array of galleries and images inside them
48    var imagesMap = [];
49    // Array containing temporary images DOM elements
50    var imagesElements = [];
51
52    // forEach polyfill for IE8
53    // http://stackoverflow.com/a/14827443/1077846
54    if(![].forEach) {
55        Array.prototype.forEach = function(callback, thisArg) {
56            for(var i = 0; i < this.length; i++)
57                callback.call(thisArg, this[i], i, this);
58        };
59    }
60
61    // filter polyfill for IE8
62    // https://gist.github.com/eliperelman/1031656
63    if(![].filter) {
64        Array.prototype.filter = function(a,b,c,d,e) {
65            /*jshint -W030 */
66            c=this;d=[];for(e=0;e<c.length;e++)a.call(b,c[e],e,c)&&d.push(c[e]);return d;
67        };
68    }
69
70    // Script entry point
71    function run(selector, userOptions) {
72        // Fill supports object
73        supports.transforms = testTransformsSupport();
74        supports.svg = testSVGSupport();
75        
76        buildOverlay();
77        
78        if(selector instanceof Array) {
79        	bindGalleryElements(selector, userOptions);
80        } else {
81	        // For each gallery bind a click event to every image inside it
82	        galleries = document.querySelectorAll(selector);
83	        [].forEach.call(
84	            galleries,
85	            function (galleryElement, galleryIndex) {
86	                // Filter 'a' elements from those not linking to images
87	                var tags = galleryElement.getElementsByTagName('a');
88	                tags = [].filter.call(tags, function(element) {
89	                    return regex.test(element.href);
90	                });
91	
92	                bindGalleryElements(tags, userOptions);
93	            }
94	        );
95        }
96    }
97    
98    function bindGalleryElements(array, userOptions) {
99    	// Get all gallery images and save them in imagesMap with custom options
100        var galleryID = imagesMap.length;
101        imagesMap.push(array);
102        imagesMap[galleryID].options = userOptions;
103
104        [].forEach.call(
105            imagesMap[galleryID],
106            function (imageElement, imageIndex) {
107                bind(imageElement, 'click', function(event) {
108                    /*jshint -W030 */
109                    event.preventDefault ? event.preventDefault() : event.returnValue = false;
110                    prepareOverlay(galleryID);
111                    showOverlay(imageIndex);
112                });
113            }
114        );
115    }
116
117    function buildOverlay() {
118        overlay = getByID('baguetteBox-overlay');
119        // Check if the overlay already exists
120        if(overlay) {
121            slider = getByID('baguetteBox-slider');
122            previousButton = getByID('previous-button');
123            nextButton = getByID('next-button');
124            closeButton = getByID('close-button');
125            return;
126        }
127        // Create overlay element
128        overlay = create('div');
129        overlay.id = 'baguetteBox-overlay';
130        document.getElementsByTagName('body')[0].appendChild(overlay);
131        // Create gallery slider element
132        slider = create('div');
133        slider.id = 'baguetteBox-slider';
134        overlay.appendChild(slider);
135        // Create all necessary buttons
136        previousButton = create('button');
137        previousButton.id = 'previous-button';
138        previousButton.innerHTML = supports.svg ? leftArrow : '&lt;';
139        overlay.appendChild(previousButton);
140
141        nextButton = create('button');
142        nextButton.id = 'next-button';
143        nextButton.innerHTML = supports.svg ? rightArrow : '&gt;';
144        overlay.appendChild(nextButton);
145
146        closeButton = create('button');
147        closeButton.id = 'close-button';
148        closeButton.innerHTML = supports.svg ? closeX : 'X';
149        overlay.appendChild(closeButton);
150
151        previousButton.className = nextButton.className = closeButton.className = 'baguetteBox-button';
152
153        bindEvents();
154    }
155
156    function bindEvents() {
157        // When clicked on the overlay (outside displayed image) close it
158        bind(overlay, 'click', function(event) {
159            if(event.target && event.target.nodeName !== "IMG" && event.target.nodeName !== "FIGCAPTION")
160                hideOverlay();
161        });
162        // Add event listeners for buttons
163        bind(previousButton, 'click', function(event) {
164            /*jshint -W030 */
165            event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
166            showPreviousImage();
167        });
168        bind(nextButton, 'click', function(event) {
169            /*jshint -W030 */
170            event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
171            showNextImage();
172        });
173        bind(closeButton, 'click', function(event) {
174            /*jshint -W030 */
175            event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
176            hideOverlay();
177        });
178        // Add touch events
179        bind(overlay, 'touchstart', function(event) {
180            // Save x axis position
181            touchStartX = event.changedTouches[0].pageX;
182        });
183        bind(overlay, 'touchmove', function(event) {
184            // If action was already triggered return
185            if(touchFlag)
186                return;
187            /*jshint -W030 */
188            event.preventDefault ? event.preventDefault() : event.returnValue = false;
189            touch = event.touches[0] || event.changedTouches[0];
190            // Move at least 40 pixels to trigger the action
191            if(touch.pageX - touchStartX > 40) {
192                touchFlag = true;
193                showPreviousImage();
194            } else if (touch.pageX - touchStartX < -40) {
195                touchFlag = true;
196                showNextImage();
197            }
198        });
199        bind(overlay, 'touchend', function(event) {
200            touchFlag = false;
201        });
202        // Activate keyboard shortcuts
203        bind(document, 'keydown', function(event) {
204            switch(event.keyCode) {
205                case 37: // Left arrow
206                    showPreviousImage();
207                    break;
208                case 39: // Right arrow
209                    showNextImage();
210                    break;
211                case 27: // Esc
212                    hideOverlay();
213                    break;
214            }
215        });
216    }
217
218    function prepareOverlay(galleryIndex) {
219        // If the same gallery is being opened prevent from loading it once again
220        if(currentGallery === galleryIndex)
221            return;
222        currentGallery = galleryIndex;
223        // Update gallery specific options
224        setOptions(imagesMap[galleryIndex].options);
225        // Empty slider of previous contents (more effective than .innerHTML = "")
226        while(slider.firstChild)
227            slider.removeChild(slider.firstChild);
228        imagesElements.length = 0;
229        // Prepare and append images containers
230        for(var i = 0, fullImage; i < imagesMap[galleryIndex].length; i++) {
231            fullImage = create('div');
232            fullImage.className = 'full-image';
233            fullImage.id = 'baguette-img-' + i;
234            imagesElements.push(fullImage);
235            slider.appendChild(imagesElements[i]);
236        }
237    }
238
239    function setOptions(newOptions) {
240        if(!newOptions)
241            newOptions = {};
242        // Fill options object
243        for(var item in defaults) {
244            options[item] = defaults[item];
245            if(typeof newOptions[item] !== 'undefined')
246                options[item] = newOptions[item];
247        }
248        /* Apply new options */
249        // Change transition for proper animation
250        slider.style.transition = slider.style.webkitTransition = (options.animation === 'fadeIn' ? 'opacity .4s ease' : 
251            options.animation === 'slideIn' ? '' : 'none');
252        // Hide buttons if necessary
253        if(options.buttons === 'auto' && ('ontouchstart' in window || imagesMap[currentGallery].length === 1))
254            options.buttons = false;
255        // Set buttons style to hide or display them
256        previousButton.style.display = nextButton.style.display = (options.buttons ? '' : 'none');
257    }
258
259    function showOverlay(index) {
260        // Return if overlay is already visible
261        if(overlay.style.display === 'block')
262            return;
263        // Set current index to a new value and load proper image
264        currentIndex = index;
265        loadImage(currentIndex, function() {
266            preloadNext(currentIndex);
267            preloadPrev(currentIndex);
268        });
269
270        updateOffset();
271        overlay.style.display = 'block';
272        // Fade in overlay
273        setTimeout(function() {
274            overlay.className = 'visible';
275            if(options.afterShow)
276                options.afterShow();
277        }, 50);
278    }
279
280    function hideOverlay() {
281        // Return if overlay is already hidden
282        if(overlay.style.display === 'none')
283            return;
284        // Fade out and hide the overlay
285        overlay.className = '';
286        setTimeout(function() {
287            overlay.style.display = 'none';
288            if(options.afterHide)
289                options.afterHide();
290        }, 500);
291    }
292
293    function loadImage(index, callback) {
294        var imageContainer = imagesElements[index];
295        // If index is invalid return
296        if(typeof imageContainer === 'undefined')
297            return;
298        // If image is already loaded run callback and return
299        if(imageContainer.getElementsByTagName('img')[0]) {
300            if(callback)
301                callback();
302            return;
303        }
304        // Get element reference, optional caption and source path
305        imageElement = imagesMap[currentGallery][index];
306        imageCaption = imageElement.getAttribute('data-caption') || imageElement.title;
307        imageSrc = getImageSrc(imageElement);
308        // Prepare image container elements
309        var figure = create('figure');
310        var image = create('img');
311        var figcaption = create('figcaption');
312        imageContainer.appendChild(figure);
313        // Add loader element
314        figure.innerHTML = '<div class="spinner">' +
315            '<div class="double-bounce1"></div>' +
316            '<div class="double-bounce2"></div>' +
317            '</div>';
318        // Set callback function when image loads
319        image.onload = function() {
320            // Remove loader element
321            var spinner = document.querySelector('#baguette-img-' + index + ' .spinner');
322            figure.removeChild(spinner);
323            if(!options.async && callback)
324                callback();
325        };
326        image.setAttribute('src', imageSrc);
327        figure.appendChild(image);
328        // Insert caption if available
329        if(options.captions && imageCaption) {
330            figcaption.innerHTML = imageCaption;
331            figure.appendChild(figcaption);
332        }
333        // Run callback
334        if(options.async && callback)
335            callback();
336    }
337
338    // Get image source location, mostly used for responsive images
339    function getImageSrc(image) {
340        // Set default image path from href
341        var result = imageElement.href;
342        // If dataset is supported find the most suitable image
343        if(image.dataset) {
344            var srcs = [];
345            // Get all possible image versions depending on the resolution
346            for(var item in image.dataset) {
347                if(item.substring(0, 3) === 'at-' && !isNaN(item.substring(3)))
348                    srcs[item.replace('at-', '')] = image.dataset[item];
349            }
350            // Sort resolutions ascending
351            keys = Object.keys(srcs).sort(function(a, b) {
352                return parseInt(a) < parseInt(b) ? -1 : 1;
353            });
354            // Get real screen resolution
355            var width = window.innerWidth * window.devicePixelRatio;
356            // Find the first image bigger than or equal to the current width
357            var i = 0;
358            while(i < keys.length - 1 && keys[i] < width)
359                i++;
360            result = srcs[keys[i]] || result;
361        }
362        return result;
363    }
364
365    // Return false at the right end of the gallery
366    function showNextImage() {
367        // Check if next image exists
368        if(currentIndex <= imagesElements.length - 2) {
369            currentIndex++;
370            updateOffset();
371            preloadNext(currentIndex);
372            return true;
373        } else if(options.animation) {
374            slider.className = 'bounce-from-right';
375            setTimeout(function() {
376                slider.className = '';
377            }, 400);
378        }
379        return false;
380    }
381
382    // Return false at the left end of the gallery
383    function showPreviousImage() {
384        // Check if previous image exists
385        if(currentIndex >= 1) {
386            currentIndex--;
387            updateOffset();
388            preloadPrev(currentIndex);
389            return true;
390        } else if(options.animation) {
391            slider.className = 'bounce-from-left';
392            setTimeout(function() {
393                slider.className = '';
394            }, 400);
395        }
396        return false;
397    }
398
399    function updateOffset() {
400        var offset = -currentIndex * 100 + '%';
401        if(options.animation === 'fadeIn') {
402            slider.style.opacity = 0;
403            setTimeout(function() {
404                /*jshint -W030 */
405                supports.transforms ?
406                    slider.style.transform = slider.style.webkitTransform = 'translate3d(' + offset + ',0,0)'
407                    : slider.style.left = offset;
408                slider.style.opacity = 1;
409            }, 400);
410        } else {
411            /*jshint -W030 */
412            supports.transforms ?
413                slider.style.transform = slider.style.webkitTransform = 'translate3d(' + offset + ',0,0)'
414                : slider.style.left = offset;
415        }
416    }
417
418    // CSS 3D Transforms test
419    function testTransformsSupport() {
420        var div = create('div');
421        return typeof div.style.perspective !== 'undefined' || typeof div.style.webkitPerspective !== 'undefined';
422    }
423
424    // Inline SVG test
425    function testSVGSupport() {
426        var div = create('div');
427        div.innerHTML = '<svg/>';
428        return (div.firstChild && div.firstChild.namespaceURI) == 'http://www.w3.org/2000/svg';
429    }
430
431    function preloadNext(index) {
432        if(index - currentIndex >= options.preload)
433            return;
434        loadImage(index + 1, function() { preloadNext(index + 1); });
435    }
436
437    function preloadPrev(index) {
438        if(currentIndex - index >= options.preload)
439            return;
440        loadImage(index - 1, function() { preloadPrev(index - 1); });
441    }
442
443    function bind(element, event, callback) {
444        if(element.addEventListener)
445            element.addEventListener(event, callback, false);
446        else // IE8 fallback
447            element.attachEvent('on' + event, callback);
448    }
449
450    function getByID(id) {
451        return document.getElementById(id);
452    }
453
454    function create(element) {
455        return document.createElement(element);
456    }
457
458    return {
459        run: run,
460        showNext: showNextImage,
461        showPrevious: showPreviousImage
462    };
463
464})();

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.