PageSourceSearch

https://lism.catholic.edu.au/app/js/lightbox.js

js lism.catholic.edu.au collected 2026-10-01 15:50:14 UTC 20,453 bytes, 509 lines download raw bytes

vendor: 5,440 bytes, lines 1-125
1/*!
2 * Lightbox v2.9.0
3 * by Lokesh Dhakar
4 *
5 * More info:
6 * http://lokeshdhakar.com/projects/lightbox2/
7 *
8 * Copyright 2007, 2015 Lokesh Dhakar
9 * Released under the MIT license
10 * https://github.com/lokesh/lightbox2/blob/master/LICENSE
11 */
12
13// Uses Node, AMD or browser globals to create a module.
14(function (root, factory) {
15    if (false && typeof define === 'function' && define.amd) {
16        // AMD. Register as an anonymous module.
17        //define(['jquery'], factory);
18    } else if (false && typeof exports === 'object') {
19        // Node. Does not work with strict CommonJS, but
20        // only CommonJS-like environments that support module.exports,
21        // like Node.
22        //module.exports = factory(require('jquery'));
23    } else {
24        // Browser globals (root is window)
25        root.lightbox = factory(root.jQuery);
26    }
27}(this, function ($) {
28
29    function Lightbox(options) {
30        this.album = [];
31        this.currentImageIndex = void 0;
32        this.init();
33
34        // options
35        this.options = $.extend({}, this.constructor.defaults);
36        this.option(options);
37    }
38
39    // Descriptions of all options available on the demo site:
40    // http://lokeshdhakar.com/projects/lightbox2/index.html#options
41    Lightbox.defaults = {
42        albumLabel: 'Image %1 of %2',
43        alwaysShowNavOnTouchDevices: false,
44        fadeDuration: 600,
45        fitImagesInViewport: true,
46        imageFadeDuration: 600,
47        // maxWidth: 800,
48        // maxHeight: 600,
49        positionFromTop: 50,
50        resizeDuration: 700,
51        showImageNumberLabel: true,
52        wrapAround: false,
53        disableScrolling: false,
54        /*
55        Sanitize Title
56        If the caption data is trusted, for example you are hardcoding it in, then leave this to false.
57        This will free you to add html tags, such as links, in the caption.
58
59        If the caption data is user submitted or from some other untrusted source, then set this to true
60        to prevent xss and other injection attacks.
61         */
62        sanitizeTitle: false
63    };
64
65    Lightbox.prototype.option = function(options) {
66        $.extend(this.options, options);
67    };
68
69    Lightbox.prototype.imageCountLabel = function(currentImageNum, totalImages) {
70        return this.options.albumLabel.replace(/%1/g, currentImageNum).replace(/%2/g, totalImages);
71    };
72
73    Lightbox.prototype.init = function() {
74        var self = this;
75        // Both enable and build methods require the body tag to be in the DOM.
76        $(document).ready(function() {
77            self.enable();
78            self.build();
79        });
80    };
81
82    // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes
83    // that contain 'lightbox'. When these are clicked, start lightbox.
84    Lightbox.prototype.enable = function() {
85        var self = this;
86        $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) {
87            self.start($(event.currentTarget));
88            return false;
89        });
90    };
91
92    // Build html for the lightbox and the overlay.
93    // Attach event handlers to the new DOM elements. click click click
94    Lightbox.prototype.build = function() {
95        var self = this;
96        if (!$('#lightbox').length && !$('#lightboxOverlay').length) {
97            $('<div id="lightboxOverlay" class="lightboxOverlay"></div><div id="lightbox" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" alt="Lightbox Image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" /><div class="lb-nav"><a class="lb-prev" name="Previous" href="" ><span>Previous</span></a><a class="lb-next" name="Next" href="" ><span>Next</span></a></div><div class="lb-loader"><a class="lb-cancel" name="Cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close" name="Close"></a></div></div></div></div>').appendTo($('body'));
98        }
99        // Cache jQuery objects
100        this.$lightbox       = $('#lightbox');
101        this.$overlay        = $('#lightboxOverlay');
102        this.$outerContainer = this.$lightbox.find('.lb-outerContainer');
103        this.$container      = this.$lightbox.find('.lb-container');
104        this.$image          = this.$lightbox.find('.lb-image');
105        this.$nav            = this.$lightbox.find('.lb-nav');
106
107        // Store css values for future lookup
108        this.containerPadding = {
109            top: parseInt(this.$container.css('padding-top'), 10),
110            right: parseInt(this.$container.css('padding-right'), 10),
111            bottom: parseInt(this.$container.css('padding-bottom'), 10),
112            left: parseInt(this.$container.css('padding-left'), 10)
113        };
114
115        this.imageBorderWidth = {
116            top: parseInt(this.$image.css('border-top-width'), 10),
117            right: parseInt(this.$image.css('border-right-width'), 10),
118            bottom: parseInt(this.$image.css('border-bottom-width'), 10),
119            left: parseInt(this.$image.css('border-left-width'), 10)
120        };
121
122        // Attach event handlers to the newly minted DOM elements
123        this.$overlay.hide().on('click', function() {
124            self.end();
125            return false;
126        });
127
128        this.$lightbox.hide().on('click', function(event) {
129            if ($(event.target).attr('id') === 'lightbox') {
130                self.end();
131            }
132            return false;
133        });
134
135        this.$outerContainer.on('click', function(event) {
136            if ($(event.target).attr('id') === 'lightbox') {
137                self.end();
138            }
139            return false;
140        });
141
142        this.$lightbox.find('.lb-prev').on('click', function() {
143            if (self.currentImageIndex === 0) {
144                self.changeImage(self.album.length - 1);
145            } else {
146                self.changeImage(self.currentImageIndex - 1);
147            }
148            return false;
149        });
150
151        this.$lightbox.find('.lb-next').on('click', function() {
152            if (self.currentImageIndex === self.album.length - 1) {
153                self.changeImage(0);
154            } else {
155                self.changeImage(self.currentImageIndex + 1);
156            }
157            return false;
158        });
159
160        /*
161          Show context menu for image on right-click
162
163          There is a div containing the navigation that spans the entire image and lives above of it. If
164          you right-click, you are right clicking this div and not the image. This prevents users from
165          saving the image or using other context menu actions with the image.
166
167          To fix this, when we detect the right mouse button is pressed down, but not yet clicked, we
168          set pointer-events to none on the nav div. This is so that the upcoming right-click event on
169          the next mouseup will bubble down to the image. Once the right-click/contextmenu event occurs
170          we set the pointer events back to auto for the nav div so it can capture hover and left-click
171          events as usual.
172         */
173        this.$nav.on('mousedown', function(event) {
174            if (event.which === 3) {
175                self.$nav.css('pointer-events', 'none');
176
177                self.$lightbox.one('contextmenu', function() {
178                    setTimeout(function() {
179                        this.$nav.css('pointer-events', 'auto');
180                    }.bind(self), 0);
181                });
182            }
183        });
184
185
186        this.$lightbox.find('.lb-loader, .lb-close').on('click', function() {
187            self.end();
188            return false;
189        });
190    };
191
192    // Show overlay and lightbox. If the image is part of a set, add siblings to album array.
193    Lightbox.prototype.start = function($link) {
194        var self    = this;
195        var $window = $(window);
196
197        $window.on('resize', $.proxy(this.sizeOverlay, this));
198
199        $('select, object, embed').css({
200            visibility: 'hidden'
201        });
202
203        this.sizeOverlay();
204
205        this.album = [];
206        var imageNumber = 0;
207
208        function addToAlbum($link) {
209            self.album.push({
210                link: $link.attr('href'),
211                title: $link.attr('data-title') || $link.attr('title')
212            });
213        }
214
215        // Support both data-lightbox attribute and rel attribute implementations
216        var dataLightboxValue = $link.attr('data-lightbox');
217        var $links;
218
219        if (dataLightboxValue) {
220            $links = $($link.prop('tagName') + '[data-lightbox="' + dataLightboxValue + '"]');
221            for (var i = 0; i < $links.length; i = ++i) {
222                addToAlbum($($links[i]));
223                if ($links[i] === $link[0]) {
224                    imageNumber = i;
225                }
226            }
227        } else {
228            if ($link.attr('rel') === 'lightbox') {
229                // If image is not part of a set
230                addToAlbum($link);
231            } else {
232                // If image is part of a set
233                $links = $($link.prop('tagName') + '[rel="' + $link.attr('rel') + '"]');
234                for (var j = 0; j < $links.length; j = ++j) {
235                    addToAlbum($($links[j]));
236                    if ($links[j] === $link[0]) {
237                        imageNumber = j;
238                    }
239                }
240            }
241        }
242
243        // Position Lightbox
244        var top  = $window.scrollTop() + this.options.positionFromTop;
245        var left = $window.scrollLeft();
246        this.$lightbox.css({
247            top: top + 'px',
248            left: left + 'px'
249        }).fadeIn(this.options.fadeDuration);
250
251        // Disable scrolling of the page while open
252        if (this.options.disableScrolling) {
253            $('body').addClass('lb-disable-scrolling');
254        }
255
256        this.changeImage(imageNumber);
257    };
258
259    // Hide most UI elements in preparation for the animated resizing of the lightbox.
260    Lightbox.prototype.changeImage = function(imageNumber) {
261        var self = this;
262
263        this.disableKeyboardNav();
264        var $image = this.$lightbox.find('.lb-image');
265
266        this.$overlay.fadeIn(this.options.fadeDuration);
267
268        $('.lb-loader').fadeIn('slow');
269        this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();
270
271        this.$outerContainer.addClass('animating');
272
273        // When image to show is preloaded, we send the width and height to sizeContainer()
274        var preloader = new Image();
275        preloader.onload = function() {
276            var $preloader;
277            var imageHeight;
278            var imageWidth;
279            var maxImageHeight;
280            var maxImageWidth;
281            var windowHeight;
282            var windowWidth;
283
284            $image.attr('src', self.album[imageNumber].link);
285
286            $preloader = $(preloader);
287
288            $image.width(preloader.width);
289            $image.height(preloader.height);
290
291            if (self.options.fitImagesInViewport) {
292                // Fit image inside the viewport.
293                // Take into account the border around the image and an additional 10px gutter on each side.
294
295                windowWidth    = $(window).width();
296                windowHeight   = $(window).height();
297                maxImageWidth  = windowWidth - self.containerPadding.left - self.containerPadding.right - self.imageBorderWidth.left - self.imageBorderWidth.right - 20;
298                maxImageHeight = windowHeight - self.containerPadding.top - self.containerPadding.bottom - self.imageBorderWidth.top - self.imageBorderWidth.bottom - 120;
299
300                // Check if image size is larger then maxWidth|maxHeight in settings
301                if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) {
302                    maxImageWidth = self.options.maxWidth;
303                }
304                if (self.options.maxHeight && self.options.maxHeight < maxImageWidth) {
305                    maxImageHeight = self.options.maxHeight;
306                }
307
308                // Is there a fitting issue?
309                if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) {
310                    if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) {
311                        imageWidth  = maxImageWidth;
312                        imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10);
313                        $image.width(imageWidth);
314                        $image.height(imageHeight);
315                    } else {
316                        imageHeight = maxImageHeight;
317                        imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10);
318                        $image.width(imageWidth);
319                        $image.height(imageHeight);
320                    }
321                }
322            }
323            self.sizeContainer($image.width(), $image.height());
324        };
325
326        preloader.src          = this.album[imageNumber].link;
327        this.currentImageIndex = imageNumber;
328    };
329
330    // Stretch overlay to fit the viewport
331    Lightbox.prototype.sizeOverlay = function() {
332        this.$overlay
333            .width($(document).width())
334            .height($(document).height());
335    };
336
337    // Animate the size of the lightbox to fit the image we are showing
338    Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {
339        var self = this;
340
341        var oldWidth  = this.$outerContainer.outerWidth();
342        var oldHeight = this.$outerContainer.outerHeight();
343        var newWidth  = imageWidth + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right;
344        var newHeight = imageHeight + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom;
345
346        function postResize() {
347            self.$lightbox.find('.lb-dataContainer').width(newWidth);
348            self.$lightbox.find('.lb-prevLink').height(newHeight);
349            self.$lightbox.find('.lb-nextLink').height(newHeight);
350            self.showImage();
351        }
352
353        if (oldWidth !== newWidth || oldHeight !== newHeight) {
354            this.$outerContainer.animate({
355                width: newWidth,
356                height: newHeight
357            }, this.options.resizeDuration, 'swing', function() {
358                postResize();
359            });
360        } else {
361            postResize();
362        }
363    };
364
365    // Display the image and its details and begin preload neighboring images.
366    Lightbox.prototype.showImage = function() {
367        this.$lightbox.find('.lb-loader').stop(true).hide();
368        this.$lightbox.find('.lb-image').fadeIn(this.options.imageFadeDuration);
369
370        this.updateNav();
371        this.updateDetails();
372        this.preloadNeighboringImages();
373        this.enableKeyboardNav();
374    };
375
376    // Display previous and next navigation if appropriate.
377    Lightbox.prototype.updateNav = function() {
378        // Check to see if the browser supports touch events. If so, we take the conservative approach
379        // and assume that mouse hover events are not supported and always show prev/next navigation
380        // arrows in image sets.
381        var alwaysShowNav = false;
382        try {
383            document.createEvent('TouchEvent');
384            alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false;
385        } catch (e) {}
386
387        this.$lightbox.find('.lb-nav').show();
388
389        if (this.album.length > 1) {
390            if (this.options.wrapAround) {
391                if (alwaysShowNav) {
392                    this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');
393                }
394                this.$lightbox.find('.lb-prev, .lb-next').show();
395            } else {
396                if (this.currentImageIndex > 0) {
397                    this.$lightbox.find('.lb-prev').show();
398                    if (alwaysShowNav) {
399                        this.$lightbox.find('.lb-prev').css('opacity', '1');
400                    }
401                }
402                if (this.currentImageIndex < this.album.length - 1) {
403                    this.$lightbox.find('.lb-next').show();
404                    if (alwaysShowNav) {
405                        this.$lightbox.find('.lb-next').css('opacity', '1');
406                    }
407                }
408            }
409        }
410    };
411
412    // Display caption, image number, and closing button.
413    Lightbox.prototype.updateDetails = function() {
414        var self = this;
415
416        // Enable anchor clicks in the injected caption html.
417        // Thanks Nate Wright for the fix. @https://github.com/NateWr
418        if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&
419            this.album[this.currentImageIndex].title !== '') {
420            var $caption = this.$lightbox.find('.lb-caption');
421            if (this.options.sanitizeTitle) {
422                $caption.text(this.album[this.currentImageIndex].title);
423            } else {
424                $caption.html(this.album[this.currentImageIndex].title);
425            }
426            $caption.fadeIn('fast')
427                .find('a').on('click', function(event) {
428                if ($(this).attr('target') !== undefined) {
429                    window.open($(this).attr('href'), $(this).attr('target'));
430                } else {
431                    location.href = $(this).attr('href');
432                }
433            });
434        }
435
436        if (this.album.length > 1 && this.options.showImageNumberLabel) {
437            var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);
438            this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast');
439        } else {
440            this.$lightbox.find('.lb-number').hide();
441        }
442
443        this.$outerContainer.removeClass('animating');
444
445        this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() {
446            return self.sizeOverlay();
447        });
448    };
449
450    // Preload previous and next images in set.
451    Lightbox.prototype.preloadNeighboringImages = function() {
452        if (this.album.length > this.currentImageIndex + 1) {
453            var preloadNext = new Image();
454            preloadNext.src = this.album[this.currentImageIndex + 1].link;
455        }
456        if (this.currentImageIndex > 0) {
457            var preloadPrev = new Image();
458            preloadPrev.src = this.album[this.currentImageIndex - 1].link;
459        }
460    };
461
462    Lightbox.prototype.enableKeyboardNav = function() {
463        $(document).on('keyup.keyboard', $.proxy(this.keyboardAction, this));
464    };
465
466    Lightbox.prototype.disableKeyboardNav = function() {
467        $(document).off('.keyboard');
468    };
469
470    Lightbox.prototype.keyboardAction = function(event) {
471        var KEYCODE_ESC        = 27;
472        var KEYCODE_LEFTARROW  = 37;
473        var KEYCODE_RIGHTARROW = 39;
474
475        var keycode = event.keyCode;
476        var key     = String.fromCharCode(keycode).toLowerCase();
477        if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) {
478            this.end();
479        } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) {
480            if (this.currentImageIndex !== 0) {
481                this.changeImage(this.currentImageIndex - 1);
482            } else if (this.options.wrapAround && this.album.length > 1) {
483                this.changeImage(this.album.length - 1);
484            }
485        } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) {
486            if (this.currentImageIndex !== this.album.length - 1) {
487                this.changeImage(this.currentImageIndex + 1);
488            } else if (this.options.wrapAround && this.album.length > 1) {
489                this.changeImage(0);
490            }
491        }
492    };
493
494    // Closing time. :-(
495    Lightbox.prototype.end = function() {
496        this.disableKeyboardNav();
497        $(window).off('resize', this.sizeOverlay);
498        this.$lightbox.fadeOut(this.options.fadeDuration);
499        this.$overlay.fadeOut(this.options.fadeDuration);
500        $('select, object, embed').css({
501            visibility: 'visible'
502        });
503        if (this.options.disableScrolling) {
504            $('body').removeClass('lb-disable-scrolling');
505        }
506    };
507
508    return new Lightbox();
509}));

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.