/* Lightbox for Bootstrap 3 by @ashleydw https://github.com/ashleydw/lightbox License: https://github.com/ashleydw/lightbox/blob/master/LICENSE */ (function() { "use strict"; var $, EkkoLightbox; $ = jQuery; EkkoLightbox = function(element, options) { var content, footer, header, _this = this; this.options = $.extend({ title: null, footer: null, remote: null }, $.fn.ekkoLightbox.defaults, options || {}); this.$element = $(element); content = ''; this.modal_id = this.options.modal_id ? this.options.modal_id : 'ekkoLightbox-' + Math.floor((Math.random() * 1000) + 1); header = ''; footer = ''; $(document.body).append(''); this.modal = $('#' + this.modal_id); this.modal_dialog = this.modal.find('.modal-dialog').first(); this.modal_content = this.modal.find('.modal-content').first(); this.modal_body = this.modal.find('.modal-body').first(); this.lightbox_container = this.modal_body.find('.ekko-lightbox-container').first(); this.lightbox_body = this.lightbox_container.find('> div:first-child').first(); this.modal_arrows = null; this.border = { top: parseFloat(this.modal_dialog.css('border-top-width')) + parseFloat(this.modal_content.css('border-top-width')) + parseFloat(this.modal_body.css('border-top-width')), right: parseFloat(this.modal_dialog.css('border-right-width')) + parseFloat(this.modal_content.css('border-right-width')) + parseFloat(this.modal_body.css('border-right-width')), bottom: parseFloat(this.modal_dialog.css('border-bottom-width')) + parseFloat(this.modal_content.css('border-bottom-width')) + parseFloat(this.modal_body.css('border-bottom-width')), left: parseFloat(this.modal_dialog.css('border-left-width')) + parseFloat(this.modal_content.css('border-left-width')) + parseFloat(this.modal_body.css('border-left-width')) }; this.padding = { top: parseFloat(this.modal_dialog.css('padding-top')) + parseFloat(this.modal_content.css('padding-top')) + parseFloat(this.modal_body.css('padding-top')), right: parseFloat(this.modal_dialog.css('padding-right')) + parseFloat(this.modal_content.css('padding-right')) + parseFloat(this.modal_body.css('padding-right')), bottom: parseFloat(this.modal_dialog.css('padding-bottom')) + parseFloat(this.modal_content.css('padding-bottom')) + parseFloat(this.modal_body.css('padding-bottom')), left: parseFloat(this.modal_dialog.css('padding-left')) + parseFloat(this.modal_content.css('padding-left')) + parseFloat(this.modal_body.css('padding-left')) }; this.modal.on('show.bs.modal', this.options.onShow.bind(this)).on('shown.bs.modal', function() { _this.modal_shown(); return _this.options.onShown.call(_this); }).on('hide.bs.modal', this.options.onHide.bind(this)).on('hidden.bs.modal', function() { if (_this.gallery) { $(document).off('keydown.ekkoLightbox'); } _this.modal.remove(); return _this.options.onHidden.call(_this); }).modal('show', options); return this.modal; }; EkkoLightbox.prototype = { modal_shown: function() { var video_id, _this = this; if (!this.options.remote) { return this.error('No remote target given'); } else { this.gallery = this.$element.data('gallery'); if (this.gallery) { if (this.options.gallery_parent_selector === 'document.body' || this.options.gallery_parent_selector === '') { this.gallery_items = $(document.body).find('*[data-toggle="lightbox"][data-gallery="' + this.gallery + '"]'); } else { this.gallery_items = this.$element.parents(this.options.gallery_parent_selector).first().find('*[data-toggle="lightbox"][data-gallery="' + this.gallery + '"]'); } this.gallery_index = this.gallery_items.index(this.$element); $(document).on('keydown.ekkoLightbox', this.navigate.bind(this)); if (this.options.directional_arrows && this.gallery_items.length > 1) { this.lightbox_container.prepend('
'); this.modal_arrows = this.lightbox_container.find('div.ekko-lightbox-nav-overlay').first(); this.left_arrow = this.lightbox_container.find('a' + this.strip_spaces(this.options.left_arrow_class)); this.left_arrow.on('click', function(event) { event.preventDefault(); return _this.navigate_left(); }); this.right_arrow = this.lightbox_container.find('a' + this.strip_spaces(this.options.right_arrow_class)); this.right_arrow.on('click', function(event) { event.preventDefault(); return _this.navigate_right(); }); } } if (this.options.type) { if (this.options.type === 'image') { return this.preloadImage(this.options.remote, true); } else if (this.options.type === 'youtube' && (video_id = this.getYoutubeId(this.options.remote))) { return this.showYoutubeVideo(video_id); } else if (this.options.type === 'vimeo') { return this.showVimeoVideo(this.options.remote); } else { return this.error("Could not detect remote target type. Force the type using data-type=\"image|youtube|vimeo\""); } } else { return this.detectRemoteType(this.options.remote); } } }, strip_stops: function(str) { return str.replace(/\./g, ''); }, strip_spaces: function(str) { return str.replace(/\s/g, ''); }, isImage: function(str) { return str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i); }, isSwf: function(str) { return str.match(/\.(swf)((\?|#).*)?$/i); }, getYoutubeId: function(str) { var match; match = str.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/); if (match && match[2].length === 11) { return match[2]; } else { return false; } }, getVimeoId: function(str) { if (str.indexOf('vimeo') > 0) { return str; } else { return false; } }, navigate: function(event) { event = event || window.event; if (event.keyCode === 39 || event.keyCode === 37) { if (event.keyCode === 39) { return this.navigate_right(); } else if (event.keyCode === 37) { return this.navigate_left(); } } }, navigate_left: function() { var src; if (this.gallery_items.length === 1) { return; } this.gallery_index--; if (this.gallery_index <= 0) { this.gallery_index = 0; this.left_arrow.css('display', 'none'); } else { this.left_arrow.css('display', 'block'); } this.right_arrow.css('display', 'block'); this.$element = $(this.gallery_items.get(this.gallery_index)); this.updateTitleAndFooter(); src = this.$element.attr('data-remote') || this.$element.attr('href'); return this.detectRemoteType(src, this.$element.attr('data-type')); }, navigate_right: function() { var next, src; if (this.gallery_items.length === 1) { return; } this.gallery_index++; if (this.gallery_index >= this.gallery_items.length - 1) { this.gallery_index = this.gallery_items.length - 1; this.right_arrow.css('display', 'none'); } else { this.right_arrow.css('display', 'block'); } this.left_arrow.css('display', 'block'); this.$element = $(this.gallery_items.get(this.gallery_index)); src = this.$element.attr('data-remote') || this.$element.attr('href'); this.updateTitleAndFooter(); this.detectRemoteType(src, this.$element.attr('data-type')); if (this.gallery_index + 1 < this.gallery_items.length) { next = $(this.gallery_items.get(this.gallery_index + 1), false); src = next.attr('data-remote') || next.attr('href'); if (next.attr('data-type') === 'image' || this.isImage(src)) { return this.preloadImage(src, false); } } }, detectRemoteType: function(src, type) { var video_id; if (type === 'image' || this.isImage(src)) { this.options.type = 'image'; return this.preloadImage(src, true); } else if (type === 'youtube' || (video_id = this.getYoutubeId(src))) { this.options.type = 'youtube'; return this.showYoutubeVideo(video_id); } else if (type === 'vimeo' || (video_id = this.getVimeoId(src))) { this.options.type = 'vimeo'; return this.showVimeoVideo(video_id); } else { return this.error("Could not detect remote target type. Force the type using data-type=\"image|youtube|vimeo\""); } }, updateTitleAndFooter: function() { var caption, footer, header, title; header = this.modal_content.find('.modal-header'); footer = this.modal_content.find('.modal-footer'); title = this.$element.data('title') || ""; caption = this.$element.data('footer') || ""; if (title || this.options.always_show_close) { header.css('display', '').find('.modal-title').html(title || " "); } else { header.css('display', 'none'); } if (caption) { footer.css('display', '').html(caption); } else { footer.css('display', 'none'); } return this; }, showLoading: function() { this.lightbox_body.html(''); return this; }, showYoutubeVideo: function(id) { var aspectRatio, height, width; aspectRatio = 560 / 315; width = this.$element.data('width') || 560; width = this.checkDimensions(width); height = width / aspectRatio; this.resize(width, height); this.lightbox_body.html(''); if (this.modal_arrows) { return this.modal_arrows.css('display', 'none'); } }, showVimeoVideo: function(id) { var aspectRatio, height, width; aspectRatio = 500 / 281; width = this.$element.data('width') || 560; width = this.checkDimensions(width); height = width / aspectRatio; this.resize(width, height); this.lightbox_body.html(''); if (this.modal_arrows) { return this.modal_arrows.css('display', 'none'); } }, error: function(message) { this.lightbox_body.html(message); return this; }, preloadImage: function(src, onLoadShowImage) { var img, _this = this; var auto_fit = function(obj,maxW,maxH){ var imgW=obj.width; var imgH=obj.height; var ratioA = imgH/imgW; var ratioB = imgW/imgH; while (imgW>maxW||imgH>maxH) { if(imgW>maxW) { imgW=maxW; imgH=maxW*ratioA; } if(imgH>maxH) { imgH=maxH; imgW=maxH*ratioB; } } obj.width= imgW; obj.height = imgH; }; img = new Image(); if ((onLoadShowImage == null) || onLoadShowImage === true) { img.onload = function() { var image; image = $(''); image.attr('src', img.src).hide(); image.addClass('img-responsive'); if (_this.modal_arrows) { _this.modal_arrows.css('display', 'block'); } auto_fit(img, $(window).width() * 0.9, $(window).height() * 0.8); _this.lightbox_body.html(image.fadeIn(600)).css("height", "auto"); return _this.resize(img.width, img.height); }; img.onerror = function() { return _this.error('Failed to load image: ' + src); }; } _this.lightbox_body.text(""); img.src = src; return img; }, resize: function(width, height) { var width_total; var _this = this; width_total = width + this.border.left + this.padding.left + this.padding.right + this.border.right; this.modal_dialog.css('width', 'auto').css('max-width', width_total); this.lightbox_container.find('a').css('padding-top', function() { _this.lightbox_body.height(_this.lightbox_body.height()); return _this.lightbox_body.height() / 2; }); return this; }, checkDimensions: function(width) { var body_width, width_total; width_total = width + this.border.left + this.padding.left + this.padding.right + this.border.right; body_width = document.body.clientWidth; if (width_total > body_width) { width = this.modal_body.width(); } return width; }, close: function() { return this.modal.modal('hide'); } }; $.fn.ekkoLightbox = function(options) { return this.each(function() { var $this; $this = $(this); options = $.extend({ remote: $this.attr('data-remote') || $this.attr('href'), gallery_parent_selector: $this.attr('data-parent'), type: $this.attr('data-type') }, options, $this.data()); new EkkoLightbox(this, options); return this; }); }; $.fn.ekkoLightbox.defaults = { gallery_parent_selector: '*:not(.row)', left_arrow_class: '.glyphicon .glyphicon-chevron-left', right_arrow_class: '.glyphicon .glyphicon-chevron-right', directional_arrows: true, type: null, always_show_close: true, onShow: function() {}, onShown: function() {}, onHide: function() {}, onHidden: function() {} }; }).call(this);