diff options
Diffstat (limited to 'build/resources/main/static/plugins/ekko-lightbox/ekko-lightbox.js')
-rw-r--r-- | build/resources/main/static/plugins/ekko-lightbox/ekko-lightbox.js | 668 |
1 files changed, 668 insertions, 0 deletions
diff --git a/build/resources/main/static/plugins/ekko-lightbox/ekko-lightbox.js b/build/resources/main/static/plugins/ekko-lightbox/ekko-lightbox.js new file mode 100644 index 0000000..f9c0574 --- /dev/null +++ b/build/resources/main/static/plugins/ekko-lightbox/ekko-lightbox.js @@ -0,0 +1,668 @@ +/*! + * Lightbox for Bootstrap by @ashleydw + * https://github.com/ashleydw/lightbox + * + * License: https://github.com/ashleydw/lightbox/blob/master/LICENSE + */ ++function ($) { + +'use strict'; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + +var Lightbox = (function ($) { + + var NAME = 'ekkoLightbox'; + var JQUERY_NO_CONFLICT = $.fn[NAME]; + + var Default = { + title: '', + footer: '', + maxWidth: 9999, + maxHeight: 9999, + showArrows: true, //display the left / right arrows or not + wrapping: true, //if true, gallery loops infinitely + type: null, //force the lightbox into image / youtube mode. if null, or not image|youtube|vimeo; detect it + alwaysShowClose: false, //always show the close button, even if there is no title + loadingMessage: '<div class="ekko-lightbox-loader"><div><div></div><div></div></div></div>', // http://tobiasahlin.com/spinkit/ + leftArrow: '<span>❮</span>', + rightArrow: '<span>❯</span>', + strings: { + close: 'Close', + fail: 'Failed to load image:', + type: 'Could not detect remote target type. Force the type using data-type' + }, + doc: document, // if in an iframe can specify top.document + onShow: function onShow() {}, + onShown: function onShown() {}, + onHide: function onHide() {}, + onHidden: function onHidden() {}, + onNavigate: function onNavigate() {}, + onContentLoaded: function onContentLoaded() {} + }; + + var Lightbox = (function () { + _createClass(Lightbox, null, [{ + key: 'Default', + + /** + Class properties: + _$element: null -> the <a> element currently being displayed + _$modal: The bootstrap modal generated + _$modalDialog: The .modal-dialog + _$modalContent: The .modal-content + _$modalBody: The .modal-body + _$modalHeader: The .modal-header + _$modalFooter: The .modal-footer + _$lightboxContainerOne: Container of the first lightbox element + _$lightboxContainerTwo: Container of the second lightbox element + _$lightboxBody: First element in the container + _$modalArrows: The overlayed arrows container + _$galleryItems: Other <a>'s available for this gallery + _galleryName: Name of the current data('gallery') showing + _galleryIndex: The current index of the _$galleryItems being shown + _config: {} the options for the modal + _modalId: unique id for the current lightbox + _padding / _border: CSS properties for the modal container; these are used to calculate the available space for the content + */ + + get: function get() { + return Default; + } + }]); + + function Lightbox($element, config) { + var _this = this; + + _classCallCheck(this, Lightbox); + + this._config = $.extend({}, Default, config); + this._$modalArrows = null; + this._galleryIndex = 0; + this._galleryName = null; + this._padding = null; + this._border = null; + this._titleIsShown = false; + this._footerIsShown = false; + this._wantedWidth = 0; + this._wantedHeight = 0; + this._touchstartX = 0; + this._touchendX = 0; + + this._modalId = 'ekkoLightbox-' + Math.floor(Math.random() * 1000 + 1); + this._$element = $element instanceof jQuery ? $element : $($element); + + this._isBootstrap3 = $.fn.modal.Constructor.VERSION[0] == 3; + + var h4 = '<h4 class="modal-title">' + (this._config.title || " ") + '</h4>'; + var btn = '<button type="button" class="close" data-dismiss="modal" aria-label="' + this._config.strings.close + '"><span aria-hidden="true">×</span></button>'; + + var header = '<div class="modal-header' + (this._config.title || this._config.alwaysShowClose ? '' : ' hide') + '">' + (this._isBootstrap3 ? btn + h4 : h4 + btn) + '</div>'; + var footer = '<div class="modal-footer' + (this._config.footer ? '' : ' hide') + '">' + (this._config.footer || " ") + '</div>'; + var body = '<div class="modal-body"><div class="ekko-lightbox-container"><div class="ekko-lightbox-item fade in show"></div><div class="ekko-lightbox-item fade"></div></div></div>'; + var dialog = '<div class="modal-dialog" role="document"><div class="modal-content">' + header + body + footer + '</div></div>'; + $(this._config.doc.body).append('<div id="' + this._modalId + '" class="ekko-lightbox modal fade" tabindex="-1" tabindex="-1" role="dialog" aria-hidden="true">' + dialog + '</div>'); + + this._$modal = $('#' + this._modalId, this._config.doc); + this._$modalDialog = this._$modal.find('.modal-dialog').first(); + this._$modalContent = this._$modal.find('.modal-content').first(); + this._$modalBody = this._$modal.find('.modal-body').first(); + this._$modalHeader = this._$modal.find('.modal-header').first(); + this._$modalFooter = this._$modal.find('.modal-footer').first(); + + this._$lightboxContainer = this._$modalBody.find('.ekko-lightbox-container').first(); + this._$lightboxBodyOne = this._$lightboxContainer.find('> div:first-child').first(); + this._$lightboxBodyTwo = this._$lightboxContainer.find('> div:last-child').first(); + + this._border = this._calculateBorders(); + this._padding = this._calculatePadding(); + + this._galleryName = this._$element.data('gallery'); + if (this._galleryName) { + this._$galleryItems = $(document.body).find('*[data-gallery="' + this._galleryName + '"]'); + this._galleryIndex = this._$galleryItems.index(this._$element); + $(document).on('keydown.ekkoLightbox', this._navigationalBinder.bind(this)); + + // add the directional arrows to the modal + if (this._config.showArrows && this._$galleryItems.length > 1) { + this._$lightboxContainer.append('<div class="ekko-lightbox-nav-overlay"><a href="#">' + this._config.leftArrow + '</a><a href="#">' + this._config.rightArrow + '</a></div>'); + this._$modalArrows = this._$lightboxContainer.find('div.ekko-lightbox-nav-overlay').first(); + this._$lightboxContainer.on('click', 'a:first-child', function (event) { + event.preventDefault(); + return _this.navigateLeft(); + }); + this._$lightboxContainer.on('click', 'a:last-child', function (event) { + event.preventDefault(); + return _this.navigateRight(); + }); + this.updateNavigation(); + } + } + + this._$modal.on('show.bs.modal', this._config.onShow.bind(this)).on('shown.bs.modal', function () { + _this._toggleLoading(true); + _this._handle(); + return _this._config.onShown.call(_this); + }).on('hide.bs.modal', this._config.onHide.bind(this)).on('hidden.bs.modal', function () { + if (_this._galleryName) { + $(document).off('keydown.ekkoLightbox'); + $(window).off('resize.ekkoLightbox'); + } + _this._$modal.remove(); + return _this._config.onHidden.call(_this); + }).modal(this._config); + + $(window).on('resize.ekkoLightbox', function () { + _this._resize(_this._wantedWidth, _this._wantedHeight); + }); + this._$lightboxContainer.on('touchstart', function () { + _this._touchstartX = event.changedTouches[0].screenX; + }).on('touchend', function () { + _this._touchendX = event.changedTouches[0].screenX; + _this._swipeGesure(); + }); + } + + _createClass(Lightbox, [{ + key: 'element', + value: function element() { + return this._$element; + } + }, { + key: 'modal', + value: function modal() { + return this._$modal; + } + }, { + key: 'navigateTo', + value: function navigateTo(index) { + + if (index < 0 || index > this._$galleryItems.length - 1) return this; + + this._galleryIndex = index; + + this.updateNavigation(); + + this._$element = $(this._$galleryItems.get(this._galleryIndex)); + this._handle(); + } + }, { + key: 'navigateLeft', + value: function navigateLeft() { + + if (!this._$galleryItems) return; + + if (this._$galleryItems.length === 1) return; + + if (this._galleryIndex === 0) { + if (this._config.wrapping) this._galleryIndex = this._$galleryItems.length - 1;else return; + } else //circular + this._galleryIndex--; + + this._config.onNavigate.call(this, 'left', this._galleryIndex); + return this.navigateTo(this._galleryIndex); + } + }, { + key: 'navigateRight', + value: function navigateRight() { + + if (!this._$galleryItems) return; + + if (this._$galleryItems.length === 1) return; + + if (this._galleryIndex === this._$galleryItems.length - 1) { + if (this._config.wrapping) this._galleryIndex = 0;else return; + } else //circular + this._galleryIndex++; + + this._config.onNavigate.call(this, 'right', this._galleryIndex); + return this.navigateTo(this._galleryIndex); + } + }, { + key: 'updateNavigation', + value: function updateNavigation() { + if (!this._config.wrapping) { + var $nav = this._$lightboxContainer.find('div.ekko-lightbox-nav-overlay'); + if (this._galleryIndex === 0) $nav.find('a:first-child').addClass('disabled');else $nav.find('a:first-child').removeClass('disabled'); + + if (this._galleryIndex === this._$galleryItems.length - 1) $nav.find('a:last-child').addClass('disabled');else $nav.find('a:last-child').removeClass('disabled'); + } + } + }, { + key: 'close', + value: function close() { + return this._$modal.modal('hide'); + } + + // helper private methods + }, { + key: '_navigationalBinder', + value: function _navigationalBinder(event) { + event = event || window.event; + if (event.keyCode === 39) return this.navigateRight(); + if (event.keyCode === 37) return this.navigateLeft(); + } + + // type detection private methods + }, { + key: '_detectRemoteType', + value: function _detectRemoteType(src, type) { + + type = type || false; + + if (!type && this._isImage(src)) type = 'image'; + if (!type && this._getYoutubeId(src)) type = 'youtube'; + if (!type && this._getVimeoId(src)) type = 'vimeo'; + if (!type && this._getInstagramId(src)) type = 'instagram'; + + if (!type || ['image', 'youtube', 'vimeo', 'instagram', 'video', 'url'].indexOf(type) < 0) type = 'url'; + + return type; + } + }, { + key: '_isImage', + value: function _isImage(string) { + return string && string.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i); + } + }, { + key: '_containerToUse', + value: function _containerToUse() { + var _this2 = this; + + // if currently showing an image, fade it out and remove + var $toUse = this._$lightboxBodyTwo; + var $current = this._$lightboxBodyOne; + + if (this._$lightboxBodyTwo.hasClass('in')) { + $toUse = this._$lightboxBodyOne; + $current = this._$lightboxBodyTwo; + } + + $current.removeClass('in show'); + setTimeout(function () { + if (!_this2._$lightboxBodyTwo.hasClass('in')) _this2._$lightboxBodyTwo.empty(); + if (!_this2._$lightboxBodyOne.hasClass('in')) _this2._$lightboxBodyOne.empty(); + }, 500); + + $toUse.addClass('in show'); + return $toUse; + } + }, { + key: '_handle', + value: function _handle() { + + var $toUse = this._containerToUse(); + this._updateTitleAndFooter(); + + var currentRemote = this._$element.attr('data-remote') || this._$element.attr('href'); + var currentType = this._detectRemoteType(currentRemote, this._$element.attr('data-type') || false); + + if (['image', 'youtube', 'vimeo', 'instagram', 'video', 'url'].indexOf(currentType) < 0) return this._error(this._config.strings.type); + + switch (currentType) { + case 'image': + this._preloadImage(currentRemote, $toUse); + this._preloadImageByIndex(this._galleryIndex, 3); + break; + case 'youtube': + this._showYoutubeVideo(currentRemote, $toUse); + break; + case 'vimeo': + this._showVimeoVideo(this._getVimeoId(currentRemote), $toUse); + break; + case 'instagram': + this._showInstagramVideo(this._getInstagramId(currentRemote), $toUse); + break; + case 'video': + this._showHtml5Video(currentRemote, $toUse); + break; + default: + // url + this._loadRemoteContent(currentRemote, $toUse); + break; + } + + return this; + } + }, { + key: '_getYoutubeId', + value: function _getYoutubeId(string) { + if (!string) return false; + var matches = string.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/); + return matches && matches[2].length === 11 ? matches[2] : false; + } + }, { + key: '_getVimeoId', + value: function _getVimeoId(string) { + return string && string.indexOf('vimeo') > 0 ? string : false; + } + }, { + key: '_getInstagramId', + value: function _getInstagramId(string) { + return string && string.indexOf('instagram') > 0 ? string : false; + } + + // layout private methods + }, { + key: '_toggleLoading', + value: function _toggleLoading(show) { + show = show || false; + if (show) { + this._$modalDialog.css('display', 'none'); + this._$modal.removeClass('in show'); + $('.modal-backdrop').append(this._config.loadingMessage); + } else { + this._$modalDialog.css('display', 'block'); + this._$modal.addClass('in show'); + $('.modal-backdrop').find('.ekko-lightbox-loader').remove(); + } + return this; + } + }, { + key: '_calculateBorders', + value: function _calculateBorders() { + return { + top: this._totalCssByAttribute('border-top-width'), + right: this._totalCssByAttribute('border-right-width'), + bottom: this._totalCssByAttribute('border-bottom-width'), + left: this._totalCssByAttribute('border-left-width') + }; + } + }, { + key: '_calculatePadding', + value: function _calculatePadding() { + return { + top: this._totalCssByAttribute('padding-top'), + right: this._totalCssByAttribute('padding-right'), + bottom: this._totalCssByAttribute('padding-bottom'), + left: this._totalCssByAttribute('padding-left') + }; + } + }, { + key: '_totalCssByAttribute', + value: function _totalCssByAttribute(attribute) { + return parseInt(this._$modalDialog.css(attribute), 10) + parseInt(this._$modalContent.css(attribute), 10) + parseInt(this._$modalBody.css(attribute), 10); + } + }, { + key: '_updateTitleAndFooter', + value: function _updateTitleAndFooter() { + var title = this._$element.data('title') || ""; + var caption = this._$element.data('footer') || ""; + + this._titleIsShown = false; + if (title || this._config.alwaysShowClose) { + this._titleIsShown = true; + this._$modalHeader.css('display', '').find('.modal-title').html(title || " "); + } else this._$modalHeader.css('display', 'none'); + + this._footerIsShown = false; + if (caption) { + this._footerIsShown = true; + this._$modalFooter.css('display', '').html(caption); + } else this._$modalFooter.css('display', 'none'); + + return this; + } + }, { + key: '_showYoutubeVideo', + value: function _showYoutubeVideo(remote, $containerForElement) { + var id = this._getYoutubeId(remote); + var query = remote.indexOf('&') > 0 ? remote.substr(remote.indexOf('&')) : ''; + var width = this._$element.data('width') || 560; + var height = this._$element.data('height') || width / (560 / 315); + return this._showVideoIframe('//www.youtube.com/embed/' + id + '?badge=0&autoplay=1&html5=1' + query, width, height, $containerForElement); + } + }, { + key: '_showVimeoVideo', + value: function _showVimeoVideo(id, $containerForElement) { + var width = this._$element.data('width') || 500; + var height = this._$element.data('height') || width / (560 / 315); + return this._showVideoIframe(id + '?autoplay=1', width, height, $containerForElement); + } + }, { + key: '_showInstagramVideo', + value: function _showInstagramVideo(id, $containerForElement) { + // instagram load their content into iframe's so this can be put straight into the element + var width = this._$element.data('width') || 612; + var height = width + 80; + id = id.substr(-1) !== '/' ? id + '/' : id; // ensure id has trailing slash + $containerForElement.html('<iframe width="' + width + '" height="' + height + '" src="' + id + 'embed/" frameborder="0" allowfullscreen></iframe>'); + this._resize(width, height); + this._config.onContentLoaded.call(this); + if (this._$modalArrows) //hide the arrows when showing video + this._$modalArrows.css('display', 'none'); + this._toggleLoading(false); + return this; + } + }, { + key: '_showVideoIframe', + value: function _showVideoIframe(url, width, height, $containerForElement) { + // should be used for videos only. for remote content use loadRemoteContent (data-type=url) + height = height || width; // default to square + $containerForElement.html('<div class="embed-responsive embed-responsive-16by9"><iframe width="' + width + '" height="' + height + '" src="' + url + '" frameborder="0" allowfullscreen class="embed-responsive-item"></iframe></div>'); + this._resize(width, height); + this._config.onContentLoaded.call(this); + if (this._$modalArrows) this._$modalArrows.css('display', 'none'); //hide the arrows when showing video + this._toggleLoading(false); + return this; + } + }, { + key: '_showHtml5Video', + value: function _showHtml5Video(url, $containerForElement) { + // should be used for videos only. for remote content use loadRemoteContent (data-type=url) + var width = this._$element.data('width') || 560; + var height = this._$element.data('height') || width / (560 / 315); + $containerForElement.html('<div class="embed-responsive embed-responsive-16by9"><video width="' + width + '" height="' + height + '" src="' + url + '" preload="auto" autoplay controls class="embed-responsive-item"></video></div>'); + this._resize(width, height); + this._config.onContentLoaded.call(this); + if (this._$modalArrows) this._$modalArrows.css('display', 'none'); //hide the arrows when showing video + this._toggleLoading(false); + return this; + } + }, { + key: '_loadRemoteContent', + value: function _loadRemoteContent(url, $containerForElement) { + var _this3 = this; + + var width = this._$element.data('width') || 560; + var height = this._$element.data('height') || 560; + + var disableExternalCheck = this._$element.data('disableExternalCheck') || false; + this._toggleLoading(false); + + // external urls are loading into an iframe + // local ajax can be loaded into the container itself + if (!disableExternalCheck && !this._isExternal(url)) { + $containerForElement.load(url, $.proxy(function () { + return _this3._$element.trigger('loaded.bs.modal');l; + })); + } else { + $containerForElement.html('<iframe src="' + url + '" frameborder="0" allowfullscreen></iframe>'); + this._config.onContentLoaded.call(this); + } + + if (this._$modalArrows) //hide the arrows when remote content + this._$modalArrows.css('display', 'none'); + + this._resize(width, height); + return this; + } + }, { + key: '_isExternal', + value: function _isExternal(url) { + var match = url.match(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/); + if (typeof match[1] === "string" && match[1].length > 0 && match[1].toLowerCase() !== location.protocol) return true; + + if (typeof match[2] === "string" && match[2].length > 0 && match[2].replace(new RegExp(':(' + ({ + "http:": 80, + "https:": 443 + })[location.protocol] + ')?$'), "") !== location.host) return true; + + return false; + } + }, { + key: '_error', + value: function _error(message) { + console.error(message); + this._containerToUse().html(message); + this._resize(300, 300); + return this; + } + }, { + key: '_preloadImageByIndex', + value: function _preloadImageByIndex(startIndex, numberOfTimes) { + + if (!this._$galleryItems) return; + + var next = $(this._$galleryItems.get(startIndex), false); + if (typeof next == 'undefined') return; + + var src = next.attr('data-remote') || next.attr('href'); + if (next.attr('data-type') === 'image' || this._isImage(src)) this._preloadImage(src, false); + + if (numberOfTimes > 0) return this._preloadImageByIndex(startIndex + 1, numberOfTimes - 1); + } + }, { + key: '_preloadImage', + value: function _preloadImage(src, $containerForImage) { + var _this4 = this; + + $containerForImage = $containerForImage || false; + + var img = new Image(); + if ($containerForImage) { + (function () { + + // if loading takes > 200ms show a loader + var loadingTimeout = setTimeout(function () { + $containerForImage.append(_this4._config.loadingMessage); + }, 200); + + img.onload = function () { + if (loadingTimeout) clearTimeout(loadingTimeout); + loadingTimeout = null; + var image = $('<img />'); + image.attr('src', img.src); + image.addClass('img-fluid'); + + // backward compatibility for bootstrap v3 + image.css('width', '100%'); + + $containerForImage.html(image); + if (_this4._$modalArrows) _this4._$modalArrows.css('display', ''); // remove display to default to css property + + _this4._resize(img.width, img.height); + _this4._toggleLoading(false); + return _this4._config.onContentLoaded.call(_this4); + }; + img.onerror = function () { + _this4._toggleLoading(false); + return _this4._error(_this4._config.strings.fail + (' ' + src)); + }; + })(); + } + + img.src = src; + return img; + } + }, { + key: '_swipeGesure', + value: function _swipeGesure() { + if (this._touchendX < this._touchstartX) { + return this.navigateRight(); + } + if (this._touchendX > this._touchstartX) { + return this.navigateLeft(); + } + } + }, { + key: '_resize', + value: function _resize(width, height) { + + height = height || width; + this._wantedWidth = width; + this._wantedHeight = height; + + var imageAspecRatio = width / height; + + // if width > the available space, scale down the expected width and height + var widthBorderAndPadding = this._padding.left + this._padding.right + this._border.left + this._border.right; + + // force 10px margin if window size > 575px + var addMargin = this._config.doc.body.clientWidth > 575 ? 20 : 0; + var discountMargin = this._config.doc.body.clientWidth > 575 ? 0 : 20; + + var maxWidth = Math.min(width + widthBorderAndPadding, this._config.doc.body.clientWidth - addMargin, this._config.maxWidth); + + if (width + widthBorderAndPadding > maxWidth) { + height = (maxWidth - widthBorderAndPadding - discountMargin) / imageAspecRatio; + width = maxWidth; + } else width = width + widthBorderAndPadding; + + var headerHeight = 0, + footerHeight = 0; + + // as the resize is performed the modal is show, the calculate might fail + // if so, default to the default sizes + if (this._footerIsShown) footerHeight = this._$modalFooter.outerHeight(true) || 55; + + if (this._titleIsShown) headerHeight = this._$modalHeader.outerHeight(true) || 67; + + var borderPadding = this._padding.top + this._padding.bottom + this._border.bottom + this._border.top; + + //calculated each time as resizing the window can cause them to change due to Bootstraps fluid margins + var margins = parseFloat(this._$modalDialog.css('margin-top')) + parseFloat(this._$modalDialog.css('margin-bottom')); + + var maxHeight = Math.min(height, $(window).height() - borderPadding - margins - headerHeight - footerHeight, this._config.maxHeight - borderPadding - headerHeight - footerHeight); + + if (height > maxHeight) { + // if height > the available height, scale down the width + width = Math.ceil(maxHeight * imageAspecRatio) + widthBorderAndPadding; + } + + this._$lightboxContainer.css('height', maxHeight); + this._$modalDialog.css('flex', 1).css('maxWidth', width); + + var modal = this._$modal.data('bs.modal'); + if (modal) { + // v4 method is mistakenly protected + try { + modal._handleUpdate(); + } catch (Exception) { + modal.handleUpdate(); + } + } + return this; + } + }], [{ + key: '_jQueryInterface', + value: function _jQueryInterface(config) { + var _this5 = this; + + config = config || {}; + return this.each(function () { + var $this = $(_this5); + var _config = $.extend({}, Lightbox.Default, $this.data(), typeof config === 'object' && config); + + new Lightbox(_this5, _config); + }); + } + }]); + + return Lightbox; + })(); + + $.fn[NAME] = Lightbox._jQueryInterface; + $.fn[NAME].Constructor = Lightbox; + $.fn[NAME].noConflict = function () { + $.fn[NAME] = JQUERY_NO_CONFLICT; + return Lightbox._jQueryInterface; + }; + + return Lightbox; +})(jQuery); +//# sourceMappingURL=ekko-lightbox.js.map + +}(jQuery); |