]> git.mxchange.org Git - friendica.git/blob - view/theme/frio/frameworks/ekko-lightbox/ekko-lightbox.js
Merge branch 'master' of ../save/merge/frio into frio_merge
[friendica.git] / view / theme / frio / frameworks / ekko-lightbox / ekko-lightbox.js
1
2 /*
3 Lightbox for Bootstrap 3 by @ashleydw
4 https://github.com/ashleydw/lightbox
5
6 License: https://github.com/ashleydw/lightbox/blob/master/LICENSE
7  */
8
9 (function() {
10   "use strict";
11   var $, EkkoLightbox;
12
13   $ = jQuery;
14
15   EkkoLightbox = function(element, options) {
16     var content, footer, header;
17     this.options = $.extend({
18       title: null,
19       footer: null,
20       remote: null
21     }, $.fn.ekkoLightbox.defaults, options || {});
22     this.$element = $(element);
23     content = '';
24     this.modal_id = this.options.modal_id ? this.options.modal_id : 'ekkoLightbox-' + Math.floor((Math.random() * 1000) + 1);
25     header = '<div class="modal-header"' + (this.options.title || this.options.always_show_close ? '' : ' style="display:none"') + '><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h4 class="modal-title">' + (this.options.title || "&nbsp;") + '</h4></div>';
26     footer = '<div class="modal-footer"' + (this.options.footer ? '' : ' style="display:none"') + '>' + this.options.footer + '</div>';
27     $(document.body).append('<div id="' + this.modal_id + '" class="ekko-lightbox modal fade" tabindex="-1"><div class="modal-dialog"><div class="modal-content">' + header + '<div class="modal-body"><div class="ekko-lightbox-container"><div></div></div></div>' + footer + '</div></div></div>');
28     this.modal = $('#' + this.modal_id);
29     this.modal_dialog = this.modal.find('.modal-dialog').first();
30     this.modal_content = this.modal.find('.modal-content').first();
31     this.modal_body = this.modal.find('.modal-body').first();
32     this.modal_header = this.modal.find('.modal-header').first();
33     this.modal_footer = this.modal.find('.modal-footer').first();
34     this.lightbox_container = this.modal_body.find('.ekko-lightbox-container').first();
35     this.lightbox_body = this.lightbox_container.find('> div:first-child').first();
36     this.showLoading();
37     this.modal_arrows = null;
38     this.border = {
39       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')),
40       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')),
41       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')),
42       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'))
43     };
44     this.padding = {
45       top: parseFloat(this.modal_dialog.css('padding-top')) + parseFloat(this.modal_content.css('padding-top')) + parseFloat(this.modal_body.css('padding-top')),
46       right: parseFloat(this.modal_dialog.css('padding-right')) + parseFloat(this.modal_content.css('padding-right')) + parseFloat(this.modal_body.css('padding-right')),
47       bottom: parseFloat(this.modal_dialog.css('padding-bottom')) + parseFloat(this.modal_content.css('padding-bottom')) + parseFloat(this.modal_body.css('padding-bottom')),
48       left: parseFloat(this.modal_dialog.css('padding-left')) + parseFloat(this.modal_content.css('padding-left')) + parseFloat(this.modal_body.css('padding-left'))
49     };
50     this.modal.on('show.bs.modal', this.options.onShow.bind(this)).on('shown.bs.modal', (function(_this) {
51       return function() {
52         _this.modal_shown();
53         return _this.options.onShown.call(_this);
54       };
55     })(this)).on('hide.bs.modal', this.options.onHide.bind(this)).on('hidden.bs.modal', (function(_this) {
56       return function() {
57         if (_this.gallery) {
58           $(document).off('keydown.ekkoLightbox');
59         }
60         _this.modal.remove();
61         return _this.options.onHidden.call(_this);
62       };
63     })(this)).modal('show', options);
64     return this.modal;
65   };
66
67   EkkoLightbox.prototype = {
68     modal_shown: function() {
69       var video_id;
70       if (!this.options.remote) {
71         return this.error('No remote target given');
72       } else {
73         this.gallery = this.$element.data('gallery');
74         if (this.gallery) {
75           if (this.options.gallery_parent_selector === 'document.body' || this.options.gallery_parent_selector === '') {
76             this.gallery_items = $(document.body).find('*[data-gallery="' + this.gallery + '"]');
77           } else {
78             this.gallery_items = this.$element.parents(this.options.gallery_parent_selector).first().find('*[data-gallery="' + this.gallery + '"]');
79           }
80           this.gallery_index = this.gallery_items.index(this.$element);
81           $(document).on('keydown.ekkoLightbox', this.navigate.bind(this));
82           if (this.options.directional_arrows && this.gallery_items.length > 1) {
83             this.lightbox_container.append('<div class="ekko-lightbox-nav-overlay"><a href="#" class="' + this.strip_stops(this.options.left_arrow_class) + '"></a><a href="#" class="' + this.strip_stops(this.options.right_arrow_class) + '"></a></div>');
84             this.modal_arrows = this.lightbox_container.find('div.ekko-lightbox-nav-overlay').first();
85             this.lightbox_container.find('a' + this.strip_spaces(this.options.left_arrow_class)).on('click', (function(_this) {
86               return function(event) {
87                 event.preventDefault();
88                 return _this.navigate_left();
89               };
90             })(this));
91             this.lightbox_container.find('a' + this.strip_spaces(this.options.right_arrow_class)).on('click', (function(_this) {
92               return function(event) {
93                 event.preventDefault();
94                 return _this.navigate_right();
95               };
96             })(this));
97           }
98         }
99         if (this.options.type) {
100           if (this.options.type === 'image') {
101             return this.preloadImage(this.options.remote, true);
102           } else if (this.options.type === 'youtube' && (video_id = this.getYoutubeId(this.options.remote))) {
103             return this.showYoutubeVideo(video_id);
104           } else if (this.options.type === 'vimeo') {
105             return this.showVimeoVideo(this.options.remote);
106           } else if (this.options.type === 'instagram') {
107             return this.showInstagramVideo(this.options.remote);
108           } else if (this.options.type === 'url') {
109             return this.loadRemoteContent(this.options.remote);
110           } else if (this.options.type === 'video') {
111             return this.showVideoIframe(this.options.remote);
112           } else {
113             return this.error("Could not detect remote target type. Force the type using data-type=\"image|youtube|vimeo|instagram|url|video\"");
114           }
115         } else {
116           return this.detectRemoteType(this.options.remote);
117         }
118       }
119     },
120     strip_stops: function(str) {
121       return str.replace(/\./g, '');
122     },
123     strip_spaces: function(str) {
124       return str.replace(/\s/g, '');
125     },
126     isImage: function(str) {
127       return str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i);
128     },
129     isSwf: function(str) {
130       return str.match(/\.(swf)((\?|#).*)?$/i);
131     },
132     getYoutubeId: function(str) {
133       var match;
134       match = str.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/);
135       if (match && match[2].length === 11) {
136         return match[2];
137       } else {
138         return false;
139       }
140     },
141     getVimeoId: function(str) {
142       if (str.indexOf('vimeo') > 0) {
143         return str;
144       } else {
145         return false;
146       }
147     },
148     getInstagramId: function(str) {
149       if (str.indexOf('instagram') > 0) {
150         return str;
151       } else {
152         return false;
153       }
154     },
155     navigate: function(event) {
156       event = event || window.event;
157       if (event.keyCode === 39 || event.keyCode === 37) {
158         if (event.keyCode === 39) {
159           return this.navigate_right();
160         } else if (event.keyCode === 37) {
161           return this.navigate_left();
162         }
163       }
164     },
165     navigateTo: function(index) {
166       var next, src;
167       if (index < 0 || index > this.gallery_items.length - 1) {
168         return this;
169       }
170       this.showLoading();
171       this.gallery_index = index;
172       this.$element = $(this.gallery_items.get(this.gallery_index));
173       this.updateTitleAndFooter();
174       src = this.$element.attr('data-remote') || this.$element.attr('href');
175       this.detectRemoteType(src, this.$element.attr('data-type') || false);
176       if (this.gallery_index + 1 < this.gallery_items.length) {
177         next = $(this.gallery_items.get(this.gallery_index + 1), false);
178         src = next.attr('data-remote') || next.attr('href');
179         if (next.attr('data-type') === 'image' || this.isImage(src)) {
180           return this.preloadImage(src, false);
181         }
182       }
183     },
184     navigate_left: function() {
185       if (this.gallery_items.length === 1) {
186         return;
187       }
188       if (this.gallery_index === 0) {
189         this.gallery_index = this.gallery_items.length - 1;
190       } else {
191         this.gallery_index--;
192       }
193       this.options.onNavigate.call(this, 'left', this.gallery_index);
194       return this.navigateTo(this.gallery_index);
195     },
196     navigate_right: function() {
197       if (this.gallery_items.length === 1) {
198         return;
199       }
200       if (this.gallery_index === this.gallery_items.length - 1) {
201         this.gallery_index = 0;
202       } else {
203         this.gallery_index++;
204       }
205       this.options.onNavigate.call(this, 'right', this.gallery_index);
206       return this.navigateTo(this.gallery_index);
207     },
208     detectRemoteType: function(src, type) {
209       var video_id;
210       type = type || false;
211       if (type === 'image' || this.isImage(src)) {
212         this.options.type = 'image';
213         return this.preloadImage(src, true);
214       } else if (type === 'youtube' || (video_id = this.getYoutubeId(src))) {
215         this.options.type = 'youtube';
216         return this.showYoutubeVideo(video_id);
217       } else if (type === 'vimeo' || (video_id = this.getVimeoId(src))) {
218         this.options.type = 'vimeo';
219         return this.showVimeoVideo(video_id);
220       } else if (type === 'instagram' || (video_id = this.getInstagramId(src))) {
221         this.options.type = 'instagram';
222         return this.showInstagramVideo(video_id);
223       } else if (type === 'video') {
224         this.options.type = 'video';
225         return this.showVideoIframe(video_id);
226       } else {
227         this.options.type = 'url';
228         return this.loadRemoteContent(src);
229       }
230     },
231     updateTitleAndFooter: function() {
232       var caption, footer, header, title;
233       header = this.modal_content.find('.modal-header');
234       footer = this.modal_content.find('.modal-footer');
235       title = this.$element.data('title') || "";
236       caption = this.$element.data('footer') || "";
237       if (title || this.options.always_show_close) {
238         header.css('display', '').find('.modal-title').html(title || "&nbsp;");
239       } else {
240         header.css('display', 'none');
241       }
242       if (caption) {
243         footer.css('display', '').html(caption);
244       } else {
245         footer.css('display', 'none');
246       }
247       return this;
248     },
249     showLoading: function() {
250       this.lightbox_body.html('<div class="modal-loading">' + this.options.loadingMessage + '</div>');
251       return this;
252     },
253     showYoutubeVideo: function(id) {
254       var height, rel, width;
255       if ((this.$element.attr('data-norelated') != null) || this.options.no_related) {
256         rel = "&rel=0";
257       } else {
258         rel = "";
259       }
260       width = this.checkDimensions(this.$element.data('width') || 560);
261       height = width / (560 / 315);
262       return this.showVideoIframe('//www.youtube.com/embed/' + id + '?badge=0&autoplay=1&html5=1' + rel, width, height);
263     },
264     showVimeoVideo: function(id) {
265       var height, width;
266       width = this.checkDimensions(this.$element.data('width') || 560);
267       height = width / (500 / 281);
268       return this.showVideoIframe(id + '?autoplay=1', width, height);
269     },
270     showInstagramVideo: function(id) {
271       var height, width;
272       width = this.checkDimensions(this.$element.data('width') || 612);
273       this.resize(width);
274       height = width + 80;
275       this.lightbox_body.html('<iframe width="' + width + '" height="' + height + '" src="' + this.addTrailingSlash(id) + 'embed/" frameborder="0" allowfullscreen></iframe>');
276       this.options.onContentLoaded.call(this);
277       if (this.modal_arrows) {
278         return this.modal_arrows.css('display', 'none');
279       }
280     },
281     showVideoIframe: function(url, width, height) {
282       height = height || width;
283       this.resize(width);
284       this.lightbox_body.html('<div class="embed-responsive embed-responsive-16by9"><iframe width="' + width + '" height="' + height + '" src="' + url + '" frameborder="0" allowfullscreen class="embed-responsive-item"></iframe></div>');
285       this.options.onContentLoaded.call(this);
286       if (this.modal_arrows) {
287         this.modal_arrows.css('display', 'none');
288       }
289       return this;
290     },
291     loadRemoteContent: function(url) {
292       var disableExternalCheck, width;
293       width = this.$element.data('width') || 560;
294       this.resize(width);
295       disableExternalCheck = this.$element.data('disableExternalCheck') || false;
296       if (!disableExternalCheck && !this.isExternal(url)) {
297         this.lightbox_body.load(url, $.proxy((function(_this) {
298           return function() {
299             return _this.$element.trigger('loaded.bs.modal');
300           };
301         })(this)));
302       } else {
303         this.lightbox_body.html('<iframe width="' + width + '" height="' + width + '" src="' + url + '" frameborder="0" allowfullscreen></iframe>');
304         this.options.onContentLoaded.call(this);
305       }
306       if (this.modal_arrows) {
307         this.modal_arrows.css('display', 'none');
308       }
309       return this;
310     },
311     isExternal: function(url) {
312       var match;
313       match = url.match(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/);
314       if (typeof match[1] === "string" && match[1].length > 0 && match[1].toLowerCase() !== location.protocol) {
315         return true;
316       }
317       if (typeof match[2] === "string" && match[2].length > 0 && match[2].replace(new RegExp(":(" + {
318         "http:": 80,
319         "https:": 443
320       }[location.protocol] + ")?$"), "") !== location.host) {
321         return true;
322       }
323       return false;
324     },
325     error: function(message) {
326       this.lightbox_body.html(message);
327       return this;
328     },
329     preloadImage: function(src, onLoadShowImage) {
330       var img;
331       img = new Image();
332       if ((onLoadShowImage == null) || onLoadShowImage === true) {
333         img.onload = (function(_this) {
334           return function() {
335             var image;
336             image = $('<img />');
337             image.attr('src', img.src);
338             image.addClass('img-responsive');
339             _this.lightbox_body.html(image);
340             if (_this.modal_arrows) {
341               _this.modal_arrows.css('display', 'block');
342             }
343             return image.load(function() {
344               if (_this.options.scale_height) {
345                 _this.scaleHeight(img.height, img.width);
346               } else {
347                 _this.resize(img.width);
348               }
349               return _this.options.onContentLoaded.call(_this);
350             });
351           };
352         })(this);
353         img.onerror = (function(_this) {
354           return function() {
355             return _this.error('Failed to load image: ' + src);
356           };
357         })(this);
358       }
359       img.src = src;
360       return img;
361     },
362     scaleHeight: function(height, width) {
363       var border_padding, factor, footer_height, header_height, margins, max_height;
364       header_height = this.modal_header.outerHeight(true) || 0;
365       footer_height = this.modal_footer.outerHeight(true) || 0;
366       if (!this.modal_footer.is(':visible')) {
367         footer_height = 0;
368       }
369       if (!this.modal_header.is(':visible')) {
370         header_height = 0;
371       }
372       border_padding = this.border.top + this.border.bottom + this.padding.top + this.padding.bottom;
373       margins = parseFloat(this.modal_dialog.css('margin-top')) + parseFloat(this.modal_dialog.css('margin-bottom'));
374       max_height = $(window).height() - border_padding - margins - header_height - footer_height;
375       factor = Math.min(max_height / height, 1);
376       this.modal_dialog.css('height', 'auto').css('max-height', max_height);
377       return this.resize(factor * width);
378     },
379     resize: function(width) {
380       var width_total;
381       width_total = width + this.border.left + this.padding.left + this.padding.right + this.border.right;
382       this.modal_dialog.css('width', 'auto').css('max-width', width_total);
383       this.lightbox_container.find('a').css('line-height', function() {
384         return $(this).parent().height() + 'px';
385       });
386       return this;
387     },
388     checkDimensions: function(width) {
389       var body_width, width_total;
390       width_total = width + this.border.left + this.padding.left + this.padding.right + this.border.right;
391       body_width = document.body.clientWidth;
392       if (width_total > body_width) {
393         width = this.modal_body.width();
394       }
395       return width;
396     },
397     close: function() {
398       return this.modal.modal('hide');
399     },
400     addTrailingSlash: function(url) {
401       if (url.substr(-1) !== '/') {
402         url += '/';
403       }
404       return url;
405     }
406   };
407
408   $.fn.ekkoLightbox = function(options) {
409     return this.each(function() {
410       var $this;
411       $this = $(this);
412       options = $.extend({
413         remote: $this.attr('data-remote') || $this.attr('href'),
414         gallery_parent_selector: $this.attr('data-parent'),
415         type: $this.attr('data-type')
416       }, options, $this.data());
417       new EkkoLightbox(this, options);
418       return this;
419     });
420   };
421
422   $.fn.ekkoLightbox.defaults = {
423     gallery_parent_selector: 'document.body',
424     left_arrow_class: '.glyphicon .glyphicon-chevron-left',
425     right_arrow_class: '.glyphicon .glyphicon-chevron-right',
426     directional_arrows: true,
427     type: null,
428     always_show_close: true,
429     no_related: false,
430     scale_height: true,
431     loadingMessage: 'Loading...',
432     onShow: function() {},
433     onShown: function() {},
434     onHide: function() {},
435     onHidden: function() {},
436     onNavigate: function() {},
437     onContentLoaded: function() {}
438   };
439
440 }).call(this);