Subversion-Projekte lars-tiefland.webanos.marine-sales.de

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
2 lars 1
/*!
2
 * Lightbox v2.10.0
3
 * by Lokesh Dhakar
4
 *
5
 * More info:
6
 * http://lokeshdhakar.com/projects/lightbox2/
7
 *
8
 * Copyright 2007, 2018 Lokesh Dhakar
9
 * Released under the MIT license
10
 * https://github.com/lokesh/lightbox2/blob/master/LICENSE
11
 *
12
 * @preserve
13
 */
14
 
15
// Uses Node, AMD or browser globals to create a module.
16
(function (root, factory) {
17
    if (typeof define === 'function' && define.amd) {
18
        // AMD. Register as an anonymous module.
19
        define(['jquery'], factory);
20
    } else if (typeof exports === 'object') {
21
        // Node. Does not work with strict CommonJS, but
22
        // only CommonJS-like environments that support module.exports,
23
        // like Node.
24
        module.exports = factory(require('jquery'));
25
    } else {
26
        // Browser globals (root is window)
27
        root.lightbox = factory(root.jQuery);
28
    }
29
}(this, function ($) {
30
 
31
  function Lightbox(options) {
32
    this.album = [];
33
    this.currentImageIndex = void 0;
34
    this.init();
35
 
36
    // options
37
    this.options = $.extend({}, this.constructor.defaults);
38
    this.option(options);
39
  }
40
 
41
  // Descriptions of all options available on the demo site:
42
  // http://lokeshdhakar.com/projects/lightbox2/index.html#options
43
  Lightbox.defaults = {
44
    albumLabel: 'Image %1 of %2',
45
    alwaysShowNavOnTouchDevices: false,
46
    fadeDuration: 600,
47
    fitImagesInViewport: true,
48
    imageFadeDuration: 600,
49
    // maxWidth: 800,
50
    // maxHeight: 600,
51
    positionFromTop: 50,
52
    resizeDuration: 700,
53
    showImageNumberLabel: true,
54
    wrapAround: false,
55
    disableScrolling: false,
56
    /*
57
    Sanitize Title
58
    If the caption data is trusted, for example you are hardcoding it in, then leave this to false.
59
    This will free you to add html tags, such as links, in the caption.
60
 
61
    If the caption data is user submitted or from some other untrusted source, then set this to true
62
    to prevent xss and other injection attacks.
63
     */
64
    sanitizeTitle: false
65
  };
66
 
67
  Lightbox.prototype.option = function(options) {
68
    $.extend(this.options, options);
69
  };
70
 
71
  Lightbox.prototype.imageCountLabel = function(currentImageNum, totalImages) {
72
    return this.options.albumLabel.replace(/%1/g, currentImageNum).replace(/%2/g, totalImages);
73
  };
74
 
75
  Lightbox.prototype.init = function() {
76
    var self = this;
77
    // Both enable and build methods require the body tag to be in the DOM.
78
    $(document).ready(function() {
79
      self.enable();
80
      self.build();
81
    });
82
  };
83
 
84
  // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes
85
  // that contain 'lightbox'. When these are clicked, start lightbox.
86
  Lightbox.prototype.enable = function() {
87
    var self = this;
88
    $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) {
89
      self.start($(event.currentTarget));
90
      return false;
91
    });
92
  };
93
 
94
  // Build html for the lightbox and the overlay.
95
  // Attach event handlers to the new DOM elements. click click click
96
  Lightbox.prototype.build = function() {
97
    if ($('#lightbox').length > 0) {
98
        return;
99
    }
100
 
101
    var self = this;
102
    $('<div id="lightboxOverlay" class="lightboxOverlay"></div><div id="lightbox" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" /><div class="lb-nav"><a class="lb-prev" href="" ></a><a class="lb-next" href="" ></a></div><div class="lb-loader"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close"></a></div></div></div></div>').appendTo($('body'));
103
 
104
    // Cache jQuery objects
105
    this.$lightbox       = $('#lightbox');
106
    this.$overlay        = $('#lightboxOverlay');
107
    this.$outerContainer = this.$lightbox.find('.lb-outerContainer');
108
    this.$container      = this.$lightbox.find('.lb-container');
109
    this.$image          = this.$lightbox.find('.lb-image');
110
    this.$nav            = this.$lightbox.find('.lb-nav');
111
 
112
    // Store css values for future lookup
113
    this.containerPadding = {
114
      top: parseInt(this.$container.css('padding-top'), 10),
115
      right: parseInt(this.$container.css('padding-right'), 10),
116
      bottom: parseInt(this.$container.css('padding-bottom'), 10),
117
      left: parseInt(this.$container.css('padding-left'), 10)
118
    };
119
 
120
    this.imageBorderWidth = {
121
      top: parseInt(this.$image.css('border-top-width'), 10),
122
      right: parseInt(this.$image.css('border-right-width'), 10),
123
      bottom: parseInt(this.$image.css('border-bottom-width'), 10),
124
      left: parseInt(this.$image.css('border-left-width'), 10)
125
    };
126
 
127
    // Attach event handlers to the newly minted DOM elements
128
    this.$overlay.hide().on('click', function() {
129
      self.end();
130
      return false;
131
    });
132
 
133
    this.$lightbox.hide().on('click', function(event) {
134
      if ($(event.target).attr('id') === 'lightbox') {
135
        self.end();
136
      }
137
      return false;
138
    });
139
 
140
    this.$outerContainer.on('click', function(event) {
141
      if ($(event.target).attr('id') === 'lightbox') {
142
        self.end();
143
      }
144
      return false;
145
    });
146
 
147
    this.$lightbox.find('.lb-prev').on('click', function() {
148
      if (self.currentImageIndex === 0) {
149
        self.changeImage(self.album.length - 1);
150
      } else {
151
        self.changeImage(self.currentImageIndex - 1);
152
      }
153
      return false;
154
    });
155
 
156
    this.$lightbox.find('.lb-next').on('click', function() {
157
      if (self.currentImageIndex === self.album.length - 1) {
158
        self.changeImage(0);
159
      } else {
160
        self.changeImage(self.currentImageIndex + 1);
161
      }
162
      return false;
163
    });
164
 
165
    /*
166
      Show context menu for image on right-click
167
 
168
      There is a div containing the navigation that spans the entire image and lives above of it. If
169
      you right-click, you are right clicking this div and not the image. This prevents users from
170
      saving the image or using other context menu actions with the image.
171
 
172
      To fix this, when we detect the right mouse button is pressed down, but not yet clicked, we
173
      set pointer-events to none on the nav div. This is so that the upcoming right-click event on
174
      the next mouseup will bubble down to the image. Once the right-click/contextmenu event occurs
175
      we set the pointer events back to auto for the nav div so it can capture hover and left-click
176
      events as usual.
177
     */
178
    this.$nav.on('mousedown', function(event) {
179
      if (event.which === 3) {
180
        self.$nav.css('pointer-events', 'none');
181
 
182
        self.$lightbox.one('contextmenu', function() {
183
          setTimeout(function() {
184
              this.$nav.css('pointer-events', 'auto');
185
          }.bind(self), 0);
186
        });
187
      }
188
    });
189
 
190
 
191
    this.$lightbox.find('.lb-loader, .lb-close').on('click', function() {
192
      self.end();
193
      return false;
194
    });
195
  };
196
 
197
  // Show overlay and lightbox. If the image is part of a set, add siblings to album array.
198
  Lightbox.prototype.start = function($link) {
199
    var self    = this;
200
    var $window = $(window);
201
 
202
    $window.on('resize', $.proxy(this.sizeOverlay, this));
203
 
204
    $('select, object, embed').css({
205
      visibility: 'hidden'
206
    });
207
 
208
    this.sizeOverlay();
209
 
210
    this.album = [];
211
    var imageNumber = 0;
212
 
213
    function addToAlbum($link) {
214
      self.album.push({
215
        alt: $link.attr('data-alt'),
216
        link: $link.attr('href'),
217
        title: $link.attr('data-title') || $link.attr('title')
218
      });
219
    }
220
 
221
    // Support both data-lightbox attribute and rel attribute implementations
222
    var dataLightboxValue = $link.attr('data-lightbox');
223
    var $links;
224
 
225
    if (dataLightboxValue) {
226
      $links = $($link.prop('tagName') + '[data-lightbox="' + dataLightboxValue + '"]');
227
      for (var i = 0; i < $links.length; i = ++i) {
228
        addToAlbum($($links[i]));
229
        if ($links[i] === $link[0]) {
230
          imageNumber = i;
231
        }
232
      }
233
    } else {
234
      if ($link.attr('rel') === 'lightbox') {
235
        // If image is not part of a set
236
        addToAlbum($link);
237
      } else {
238
        // If image is part of a set
239
        $links = $($link.prop('tagName') + '[rel="' + $link.attr('rel') + '"]');
240
        for (var j = 0; j < $links.length; j = ++j) {
241
          addToAlbum($($links[j]));
242
          if ($links[j] === $link[0]) {
243
            imageNumber = j;
244
          }
245
        }
246
      }
247
    }
248
 
249
    // Position Lightbox
250
    var top  = $window.scrollTop() + this.options.positionFromTop;
251
    var left = $window.scrollLeft();
252
    this.$lightbox.css({
253
      top: top + 'px',
254
      left: left + 'px'
255
    }).fadeIn(this.options.fadeDuration);
256
 
257
    // Disable scrolling of the page while open
258
    if (this.options.disableScrolling) {
259
      $('html').addClass('lb-disable-scrolling');
260
    }
261
 
262
    this.changeImage(imageNumber);
263
  };
264
 
265
  // Hide most UI elements in preparation for the animated resizing of the lightbox.
266
  Lightbox.prototype.changeImage = function(imageNumber) {
267
    var self = this;
268
 
269
    this.disableKeyboardNav();
270
    var $image = this.$lightbox.find('.lb-image');
271
 
272
    this.$overlay.fadeIn(this.options.fadeDuration);
273
 
274
    $('.lb-loader').fadeIn('slow');
275
    this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();
276
 
277
    this.$outerContainer.addClass('animating');
278
 
279
    // When image to show is preloaded, we send the width and height to sizeContainer()
280
    var preloader = new Image();
281
    preloader.onload = function() {
282
      var $preloader;
283
      var imageHeight;
284
      var imageWidth;
285
      var maxImageHeight;
286
      var maxImageWidth;
287
      var windowHeight;
288
      var windowWidth;
289
 
290
      $image.attr({
291
        'alt': self.album[imageNumber].alt,
292
        'src': self.album[imageNumber].link
293
      });
294
 
295
      $preloader = $(preloader);
296
 
297
      $image.width(preloader.width);
298
      $image.height(preloader.height);
299
 
300
      if (self.options.fitImagesInViewport) {
301
        // Fit image inside the viewport.
302
        // Take into account the border around the image and an additional 10px gutter on each side.
303
 
304
        windowWidth    = $(window).width();
305
        windowHeight   = $(window).height();
306
        maxImageWidth  = windowWidth - self.containerPadding.left - self.containerPadding.right - self.imageBorderWidth.left - self.imageBorderWidth.right - 20;
307
        maxImageHeight = windowHeight - self.containerPadding.top - self.containerPadding.bottom - self.imageBorderWidth.top - self.imageBorderWidth.bottom - 120;
308
 
309
        // Check if image size is larger then maxWidth|maxHeight in settings
310
        if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) {
311
          maxImageWidth = self.options.maxWidth;
312
        }
313
        if (self.options.maxHeight && self.options.maxHeight < maxImageWidth) {
314
          maxImageHeight = self.options.maxHeight;
315
        }
316
 
317
        // Is the current image's width or height is greater than the maxImageWidth or maxImageHeight
318
        // option than we need to size down while maintaining the aspect ratio.
319
        if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) {
320
          if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) {
321
            imageWidth  = maxImageWidth;
322
            imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10);
323
            $image.width(imageWidth);
324
            $image.height(imageHeight);
325
          } else {
326
            imageHeight = maxImageHeight;
327
            imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10);
328
            $image.width(imageWidth);
329
            $image.height(imageHeight);
330
          }
331
        }
332
      }
333
      self.sizeContainer($image.width(), $image.height());
334
    };
335
 
336
    preloader.src          = this.album[imageNumber].link;
337
    this.currentImageIndex = imageNumber;
338
  };
339
 
340
  // Stretch overlay to fit the viewport
341
  Lightbox.prototype.sizeOverlay = function() {
342
    this.$overlay
343
      .width($(document).width())
344
      .height($(document).height());
345
  };
346
 
347
  // Animate the size of the lightbox to fit the image we are showing
348
  Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {
349
    var self = this;
350
 
351
    var oldWidth  = this.$outerContainer.outerWidth();
352
    var oldHeight = this.$outerContainer.outerHeight();
353
    var newWidth  = imageWidth + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right;
354
    var newHeight = imageHeight + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom;
355
 
356
    function postResize() {
357
      self.$lightbox.find('.lb-dataContainer').width(newWidth);
358
      self.$lightbox.find('.lb-prevLink').height(newHeight);
359
      self.$lightbox.find('.lb-nextLink').height(newHeight);
360
      self.showImage();
361
    }
362
 
363
    if (oldWidth !== newWidth || oldHeight !== newHeight) {
364
      this.$outerContainer.animate({
365
        width: newWidth,
366
        height: newHeight
367
      }, this.options.resizeDuration, 'swing', function() {
368
        postResize();
369
      });
370
    } else {
371
      postResize();
372
    }
373
  };
374
 
375
  // Display the image and its details and begin preload neighboring images.
376
  Lightbox.prototype.showImage = function() {
377
    this.$lightbox.find('.lb-loader').stop(true).hide();
378
    this.$lightbox.find('.lb-image').fadeIn(this.options.imageFadeDuration);
379
 
380
    this.updateNav();
381
    this.updateDetails();
382
    this.preloadNeighboringImages();
383
    this.enableKeyboardNav();
384
  };
385
 
386
  // Display previous and next navigation if appropriate.
387
  Lightbox.prototype.updateNav = function() {
388
    // Check to see if the browser supports touch events. If so, we take the conservative approach
389
    // and assume that mouse hover events are not supported and always show prev/next navigation
390
    // arrows in image sets.
391
    var alwaysShowNav = false;
392
    try {
393
      document.createEvent('TouchEvent');
394
      alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false;
395
    } catch (e) {}
396
 
397
    this.$lightbox.find('.lb-nav').show();
398
 
399
    if (this.album.length > 1) {
400
      if (this.options.wrapAround) {
401
        if (alwaysShowNav) {
402
          this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');
403
        }
404
        this.$lightbox.find('.lb-prev, .lb-next').show();
405
      } else {
406
        if (this.currentImageIndex > 0) {
407
          this.$lightbox.find('.lb-prev').show();
408
          if (alwaysShowNav) {
409
            this.$lightbox.find('.lb-prev').css('opacity', '1');
410
          }
411
        }
412
        if (this.currentImageIndex < this.album.length - 1) {
413
          this.$lightbox.find('.lb-next').show();
414
          if (alwaysShowNav) {
415
            this.$lightbox.find('.lb-next').css('opacity', '1');
416
          }
417
        }
418
      }
419
    }
420
  };
421
 
422
  // Display caption, image number, and closing button.
423
  Lightbox.prototype.updateDetails = function() {
424
    var self = this;
425
 
426
    // Enable anchor clicks in the injected caption html.
427
    // Thanks Nate Wright for the fix. @https://github.com/NateWr
428
    if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&
429
      this.album[this.currentImageIndex].title !== '') {
430
      var $caption = this.$lightbox.find('.lb-caption');
431
      if (this.options.sanitizeTitle) {
432
        $caption.text(this.album[this.currentImageIndex].title);
433
      } else {
434
        $caption.html(this.album[this.currentImageIndex].title);
435
      }
436
      $caption.fadeIn('fast')
437
        .find('a').on('click', function(event) {
438
          if ($(this).attr('target') !== undefined) {
439
            window.open($(this).attr('href'), $(this).attr('target'));
440
          } else {
441
            location.href = $(this).attr('href');
442
          }
443
        });
444
    }
445
 
446
    if (this.album.length > 1 && this.options.showImageNumberLabel) {
447
      var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);
448
      this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast');
449
    } else {
450
      this.$lightbox.find('.lb-number').hide();
451
    }
452
 
453
    this.$outerContainer.removeClass('animating');
454
 
455
    this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() {
456
      return self.sizeOverlay();
457
    });
458
  };
459
 
460
  // Preload previous and next images in set.
461
  Lightbox.prototype.preloadNeighboringImages = function() {
462
    if (this.album.length > this.currentImageIndex + 1) {
463
      var preloadNext = new Image();
464
      preloadNext.src = this.album[this.currentImageIndex + 1].link;
465
    }
466
    if (this.currentImageIndex > 0) {
467
      var preloadPrev = new Image();
468
      preloadPrev.src = this.album[this.currentImageIndex - 1].link;
469
    }
470
  };
471
 
472
  Lightbox.prototype.enableKeyboardNav = function() {
473
    $(document).on('keyup.keyboard', $.proxy(this.keyboardAction, this));
474
  };
475
 
476
  Lightbox.prototype.disableKeyboardNav = function() {
477
    $(document).off('.keyboard');
478
  };
479
 
480
  Lightbox.prototype.keyboardAction = function(event) {
481
    var KEYCODE_ESC        = 27;
482
    var KEYCODE_LEFTARROW  = 37;
483
    var KEYCODE_RIGHTARROW = 39;
484
 
485
    var keycode = event.keyCode;
486
    var key     = String.fromCharCode(keycode).toLowerCase();
487
    if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) {
488
      this.end();
489
    } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) {
490
      if (this.currentImageIndex !== 0) {
491
        this.changeImage(this.currentImageIndex - 1);
492
      } else if (this.options.wrapAround && this.album.length > 1) {
493
        this.changeImage(this.album.length - 1);
494
      }
495
    } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) {
496
      if (this.currentImageIndex !== this.album.length - 1) {
497
        this.changeImage(this.currentImageIndex + 1);
498
      } else if (this.options.wrapAround && this.album.length > 1) {
499
        this.changeImage(0);
500
      }
501
    }
502
  };
503
 
504
  // Closing time. :-(
505
  Lightbox.prototype.end = function() {
506
    this.disableKeyboardNav();
507
    $(window).off('resize', this.sizeOverlay);
508
    this.$lightbox.fadeOut(this.options.fadeDuration);
509
    this.$overlay.fadeOut(this.options.fadeDuration);
510
    $('select, object, embed').css({
511
      visibility: 'visible'
512
    });
513
    if (this.options.disableScrolling) {
514
      $('html').removeClass('lb-disable-scrolling');
515
    }
516
  };
517
 
518
  return new Lightbox();
519
}));