PageSourceSearch

https://sohoeditors.com/js/ekko-lightbox.js?cache=no

js sohoeditors.com collected 2026-10-04 13:23:15 UTC 16,904 bytes, 399 lines download raw bytes

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

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.