From e2e707595b54d38a72e013a768d1eb7e20941908 Mon Sep 17 00:00:00 2001 From: franzz Date: Thu, 9 May 2019 19:27:04 +0200 Subject: [PATCH] add lightbox unminified library --- script/lightbox.js | 534 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 534 insertions(+) create mode 100644 script/lightbox.js diff --git a/script/lightbox.js b/script/lightbox.js new file mode 100644 index 0000000..e349c6e --- /dev/null +++ b/script/lightbox.js @@ -0,0 +1,534 @@ +/*! + * Lightbox v2.11.0 + * by Lokesh Dhakar + * + * More info: + * http://lokeshdhakar.com/projects/lightbox2/ + * + * Copyright 2007, 2018, 2019 Lokesh Dhakar + * Released under the MIT license + * https://github.com/lokesh/lightbox2/blob/master/LICENSE + * + * @preserve + */ + +// Uses Node, AMD or browser globals to create a module. +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(require('jquery')); + } else { + // Browser globals (root is window) + root.lightbox = factory(root.jQuery); + } +}(this, function ($) { + + function Lightbox(options) { + this.album = []; + this.currentImageIndex = void 0; + this.init(); + + // options + this.options = $.extend({}, this.constructor.defaults); + this.option(options); + } + + // Descriptions of all options available on the demo site: + // http://lokeshdhakar.com/projects/lightbox2/index.html#options + Lightbox.defaults = { + albumLabel: 'Image %1 of %2', + alwaysShowNavOnTouchDevices: false, + fadeDuration: 600, + fitImagesInViewport: true, + imageFadeDuration: 600, + // maxWidth: 800, + // maxHeight: 600, + positionFromTop: 50, + resizeDuration: 700, + showImageNumberLabel: true, + wrapAround: false, + disableScrolling: false, + /* + Sanitize Title + If the caption data is trusted, for example you are hardcoding it in, then leave this to false. + This will free you to add html tags, such as links, in the caption. + + If the caption data is user submitted or from some other untrusted source, then set this to true + to prevent xss and other injection attacks. + */ + sanitizeTitle: false + }; + + Lightbox.prototype.option = function(options) { + $.extend(this.options, options); + }; + + Lightbox.prototype.imageCountLabel = function(currentImageNum, totalImages) { + return this.options.albumLabel.replace(/%1/g, currentImageNum).replace(/%2/g, totalImages); + }; + + Lightbox.prototype.init = function() { + var self = this; + // Both enable and build methods require the body tag to be in the DOM. + $(document).ready(function() { + self.enable(); + self.build(); + }); + }; + + // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes + // that contain 'lightbox'. When these are clicked, start lightbox. + Lightbox.prototype.enable = function() { + var self = this; + $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) { + self.start($(event.currentTarget)); + return false; + }); + }; + + // Build html for the lightbox and the overlay. + // Attach event handlers to the new DOM elements. click click click + Lightbox.prototype.build = function() { + if ($('#lightbox').length > 0) { + return; + } + + var self = this; + $('
').appendTo($('body')); + + // Cache jQuery objects + this.$lightbox = $('#lightbox'); + this.$overlay = $('#lightboxOverlay'); + this.$outerContainer = this.$lightbox.find('.lb-outerContainer'); + this.$container = this.$lightbox.find('.lb-container'); + this.$image = this.$lightbox.find('.lb-image'); + this.$nav = this.$lightbox.find('.lb-nav'); + + // Store css values for future lookup + this.containerPadding = { + top: parseInt(this.$container.css('padding-top'), 10), + right: parseInt(this.$container.css('padding-right'), 10), + bottom: parseInt(this.$container.css('padding-bottom'), 10), + left: parseInt(this.$container.css('padding-left'), 10) + }; + + this.imageBorderWidth = { + top: parseInt(this.$image.css('border-top-width'), 10), + right: parseInt(this.$image.css('border-right-width'), 10), + bottom: parseInt(this.$image.css('border-bottom-width'), 10), + left: parseInt(this.$image.css('border-left-width'), 10) + }; + + // Attach event handlers to the newly minted DOM elements + this.$overlay.hide().on('click', function() { + self.end(); + return false; + }); + + this.$lightbox.hide().on('click', function(event) { + if ($(event.target).attr('id') === 'lightbox') { + self.end(); + } + return false; + }); + + this.$outerContainer.on('click', function(event) { + if ($(event.target).attr('id') === 'lightbox') { + self.end(); + } + return false; + }); + + this.$lightbox.find('.lb-prev').on('click', function() { + if (self.currentImageIndex === 0) { + self.changeImage(self.album.length - 1); + } else { + self.changeImage(self.currentImageIndex - 1); + } + return false; + }); + + this.$lightbox.find('.lb-next').on('click', function() { + if (self.currentImageIndex === self.album.length - 1) { + self.changeImage(0); + } else { + self.changeImage(self.currentImageIndex + 1); + } + return false; + }); + + /* + Show context menu for image on right-click + + There is a div containing the navigation that spans the entire image and lives above of it. If + you right-click, you are right clicking this div and not the image. This prevents users from + saving the image or using other context menu actions with the image. + + To fix this, when we detect the right mouse button is pressed down, but not yet clicked, we + set pointer-events to none on the nav div. This is so that the upcoming right-click event on + the next mouseup will bubble down to the image. Once the right-click/contextmenu event occurs + we set the pointer events back to auto for the nav div so it can capture hover and left-click + events as usual. + */ + this.$nav.on('mousedown', function(event) { + if (event.which === 3) { + self.$nav.css('pointer-events', 'none'); + + self.$lightbox.one('contextmenu', function() { + setTimeout(function() { + this.$nav.css('pointer-events', 'auto'); + }.bind(self), 0); + }); + } + }); + + + this.$lightbox.find('.lb-loader, .lb-close').on('click', function() { + self.end(); + return false; + }); + }; + + // Show overlay and lightbox. If the image is part of a set, add siblings to album array. + Lightbox.prototype.start = function($link) { + var self = this; + var $window = $(window); + + $window.on('resize', $.proxy(this.sizeOverlay, this)); + + $('select, object, embed').css({ + visibility: 'hidden' + }); + + this.sizeOverlay(); + + this.album = []; + var imageNumber = 0; + + function addToAlbum($link) { + self.album.push({ + alt: $link.attr('data-alt'), + link: $link.attr('href'), + title: $link.attr('data-title') || $link.attr('title') + //ADDED-START + , orientation: $link.attr('data-orientation') + //ADDED-END + }); + } + + // Support both data-lightbox attribute and rel attribute implementations + var dataLightboxValue = $link.attr('data-lightbox'); + var $links; + + if (dataLightboxValue) { + $links = $($link.prop('tagName') + '[data-lightbox="' + dataLightboxValue + '"]'); + for (var i = 0; i < $links.length; i = ++i) { + addToAlbum($($links[i])); + if ($links[i] === $link[0]) { + imageNumber = i; + } + } + } else { + if ($link.attr('rel') === 'lightbox') { + // If image is not part of a set + addToAlbum($link); + } else { + // If image is part of a set + $links = $($link.prop('tagName') + '[rel="' + $link.attr('rel') + '"]'); + for (var j = 0; j < $links.length; j = ++j) { + addToAlbum($($links[j])); + if ($links[j] === $link[0]) { + imageNumber = j; + } + } + } + } + + // Position Lightbox + var top = $window.scrollTop() + this.options.positionFromTop; + var left = $window.scrollLeft(); + this.$lightbox.css({ + top: top + 'px', + left: left + 'px' + }).fadeIn(this.options.fadeDuration); + + // Disable scrolling of the page while open + if (this.options.disableScrolling) { + $('html').addClass('lb-disable-scrolling'); + } + + this.changeImage(imageNumber); + }; + + // Hide most UI elements in preparation for the animated resizing of the lightbox. + Lightbox.prototype.changeImage = function(imageNumber) { + var self = this; + + this.disableKeyboardNav(); + var $image = this.$lightbox.find('.lb-image'); + + this.$overlay.fadeIn(this.options.fadeDuration); + + $('.lb-loader').fadeIn('slow'); + this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide(); + + this.$outerContainer.addClass('animating'); + + // When image to show is preloaded, we send the width and height to sizeContainer() + var preloader = new Image(); + preloader.onload = function(e) { + var $preloader; + var imageHeight; + var imageWidth; + var maxImageHeight; + var maxImageWidth; + var windowHeight; + var windowWidth; + + $image.attr({ + 'alt': self.album[imageNumber].alt, + 'src': self.album[imageNumber].link + }); + + $preloader = $(preloader); + + //ADDED-START + var sOrientation = self.album[imageNumber].orientation + if(sOrientation == '-90' || sOrientation == '90') { + var sWidth = preloader.width; + var sHeight = preloader.height; + preloader.width = sHeight; + preloader.height = sWidth; + } + //ADDED-END + + console.log(sOrientation); + + $image.width(preloader.width); + $image.height(preloader.height); + + if (self.options.fitImagesInViewport) { + // Fit image inside the viewport. + // Take into account the border around the image and an additional 10px gutter on each side. + + windowWidth = $(window).width(); + windowHeight = $(window).height(); + maxImageWidth = windowWidth - self.containerPadding.left - self.containerPadding.right - self.imageBorderWidth.left - self.imageBorderWidth.right - 20; + maxImageHeight = windowHeight - self.containerPadding.top - self.containerPadding.bottom - self.imageBorderWidth.top - self.imageBorderWidth.bottom - 120; + + // Check if image size is larger then maxWidth|maxHeight in settings + if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) { + maxImageWidth = self.options.maxWidth; + } + if (self.options.maxHeight && self.options.maxHeight < maxImageWidth) { + maxImageHeight = self.options.maxHeight; + } + + // Is the current image's width or height is greater than the maxImageWidth or maxImageHeight + // option than we need to size down while maintaining the aspect ratio. + if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) { + if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) { + imageWidth = maxImageWidth; + imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10); + $image.width(imageWidth); + $image.height(imageHeight); + } else { + imageHeight = maxImageHeight; + imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10); + $image.width(imageWidth); + $image.height(imageHeight); + } + } + } + self.sizeContainer($image.width(), $image.height()); + }; + + preloader.src = this.album[imageNumber].link; + this.currentImageIndex = imageNumber; + }; + + // Stretch overlay to fit the viewport + Lightbox.prototype.sizeOverlay = function() { + this.$overlay + .width($(document).width()) + .height($(document).height()); + }; + + // Animate the size of the lightbox to fit the image we are showing + Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) { + var self = this; + + var oldWidth = this.$outerContainer.outerWidth(); + var oldHeight = this.$outerContainer.outerHeight(); + var newWidth = imageWidth + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right; + var newHeight = imageHeight + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom; + + function postResize() { + self.$lightbox.find('.lb-dataContainer').width(newWidth); + self.$lightbox.find('.lb-prevLink').height(newHeight); + self.$lightbox.find('.lb-nextLink').height(newHeight); + self.showImage(); + } + + if (oldWidth !== newWidth || oldHeight !== newHeight) { + this.$outerContainer.animate({ + width: newWidth, + height: newHeight + }, this.options.resizeDuration, 'swing', function() { + postResize(); + }); + } else { + postResize(); + } + }; + + // Display the image and its details and begin preload neighboring images. + Lightbox.prototype.showImage = function() { + this.$lightbox.find('.lb-loader').stop(true).hide(); + this.$lightbox.find('.lb-image').fadeIn(this.options.imageFadeDuration); + + this.updateNav(); + this.updateDetails(); + this.preloadNeighboringImages(); + this.enableKeyboardNav(); + }; + + // Display previous and next navigation if appropriate. + Lightbox.prototype.updateNav = function() { + // Check to see if the browser supports touch events. If so, we take the conservative approach + // and assume that mouse hover events are not supported and always show prev/next navigation + // arrows in image sets. + var alwaysShowNav = false; + try { + document.createEvent('TouchEvent'); + alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false; + } catch (e) {} + + this.$lightbox.find('.lb-nav').show(); + + if (this.album.length > 1) { + if (this.options.wrapAround) { + if (alwaysShowNav) { + this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1'); + } + this.$lightbox.find('.lb-prev, .lb-next').show(); + } else { + if (this.currentImageIndex > 0) { + this.$lightbox.find('.lb-prev').show(); + if (alwaysShowNav) { + this.$lightbox.find('.lb-prev').css('opacity', '1'); + } + } + if (this.currentImageIndex < this.album.length - 1) { + this.$lightbox.find('.lb-next').show(); + if (alwaysShowNav) { + this.$lightbox.find('.lb-next').css('opacity', '1'); + } + } + } + } + }; + + // Display caption, image number, and closing button. + Lightbox.prototype.updateDetails = function() { + var self = this; + + // Enable anchor clicks in the injected caption html. + // Thanks Nate Wright for the fix. @https://github.com/NateWr + if (typeof this.album[this.currentImageIndex].title !== 'undefined' && + this.album[this.currentImageIndex].title !== '') { + var $caption = this.$lightbox.find('.lb-caption'); + if (this.options.sanitizeTitle) { + $caption.text(this.album[this.currentImageIndex].title); + } else { + $caption.html(this.album[this.currentImageIndex].title); + } + $caption.fadeIn('fast') + .find('a').on('click', function(event) { + if ($(this).attr('target') !== undefined) { + window.open($(this).attr('href'), $(this).attr('target')); + } else { + location.href = $(this).attr('href'); + } + }); + } + + if (this.album.length > 1 && this.options.showImageNumberLabel) { + var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length); + this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast'); + } else { + this.$lightbox.find('.lb-number').hide(); + } + + this.$outerContainer.removeClass('animating'); + + this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() { + return self.sizeOverlay(); + }); + }; + + // Preload previous and next images in set. + Lightbox.prototype.preloadNeighboringImages = function() { + if (this.album.length > this.currentImageIndex + 1) { + var preloadNext = new Image(); + preloadNext.src = this.album[this.currentImageIndex + 1].link; + } + if (this.currentImageIndex > 0) { + var preloadPrev = new Image(); + preloadPrev.src = this.album[this.currentImageIndex - 1].link; + } + }; + + Lightbox.prototype.enableKeyboardNav = function() { + $(document).on('keyup.keyboard', $.proxy(this.keyboardAction, this)); + }; + + Lightbox.prototype.disableKeyboardNav = function() { + $(document).off('.keyboard'); + }; + + Lightbox.prototype.keyboardAction = function(event) { + var KEYCODE_ESC = 27; + var KEYCODE_LEFTARROW = 37; + var KEYCODE_RIGHTARROW = 39; + + var keycode = event.keyCode; + var key = String.fromCharCode(keycode).toLowerCase(); + if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) { + this.end(); + } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) { + if (this.currentImageIndex !== 0) { + this.changeImage(this.currentImageIndex - 1); + } else if (this.options.wrapAround && this.album.length > 1) { + this.changeImage(this.album.length - 1); + } + } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) { + if (this.currentImageIndex !== this.album.length - 1) { + this.changeImage(this.currentImageIndex + 1); + } else if (this.options.wrapAround && this.album.length > 1) { + this.changeImage(0); + } + } + }; + + // Closing time. :-( + Lightbox.prototype.end = function() { + this.disableKeyboardNav(); + $(window).off('resize', this.sizeOverlay); + this.$lightbox.fadeOut(this.options.fadeDuration); + this.$overlay.fadeOut(this.options.fadeDuration); + $('select, object, embed').css({ + visibility: 'visible' + }); + if (this.options.disableScrolling) { + $('html').removeClass('lb-disable-scrolling'); + } + }; + + return new Lightbox(); +}));