PageSourceSearch

https://spac.gov.jo/Scripts/lightbox/lightbox.js

js spac.gov.jo collected 2026-10-08 07:25:00 UTC 18,249 bytes, 510 lines download raw bytes

vendor: 4,910 bytes, lines 1-126
1/*!
2 * Lightbox v2.9.0
3 * by Lokesh Dhakar
4 *
5 * More info:
6 * http://lokeshdhakar.com/projects/lightbox2/
7 *
8 * Copyright 2007, 2015 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    var self = this;
98    $('<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'));
99
100    // Cache jQuery objects
101    this.$lightbox       = $('#lightbox');
102    this.$overlay        = $('#lightboxOverlay');
103    this.$outerContainer = this.$lightbox.find('.lb-outerContainer');
104    this.$container      = this.$lightbox.find('.lb-container');
105    this.$image          = this.$lightbox.find('.lb-image');
106    this.$nav            = this.$lightbox.find('.lb-nav');
107
108    // Store css values for future lookup
109    this.containerPadding = {
110      top: parseInt(this.$container.css('padding-top'), 10),
111      right: parseInt(this.$container.css('padding-right'), 10),
112      bottom: parseInt(this.$container.css('padding-bottom'), 10),
113      left: parseInt(this.$container.css('padding-left'), 10)
114    };
115
116    this.imageBorderWidth = {
117      top: parseInt(this.$image.css('border-top-width'), 10),
118      right: parseInt(this.$image.css('border-right-width'), 10),
119      bottom: parseInt(this.$image.css('border-bottom-width'), 10),
120      left: parseInt(this.$image.css('border-left-width'), 10)
121    };
122
123    // Attach event handlers to the newly minted DOM elements
124    this.$overlay.hide().on('click', function() {
125      self.end();
126      return false;
127    });
128
129    this.$lightbox.hide().on('click', function(event) {
130      if ($(event.target).attr('id') === 'lightbox') {
131        self.end();
132      }
133      return false;
134    });
135
136    this.$outerContainer.on('click', function(event) {
137      if ($(event.target).attr('id') === 'lightbox') {
138        self.end();
139      }
140      return false;
141    });
142
143    this.$lightbox.find('.lb-prev').on('click', function() {
144      if (self.currentImageIndex === 0) {
145        self.changeImage(self.album.length - 1);
146      } else {
147        self.changeImage(self.currentImageIndex - 1);
148      }
149      return false;
150    });
151
152    this.$lightbox.find('.lb-next').on('click', function() {
153      if (self.currentImageIndex === self.album.length - 1) {
154        self.changeImage(0);
155      } else {
156        self.changeImage(self.currentImageIndex + 1);
157      }
158      return false;
159    });
160
161    /*
162      Show context menu for image on right-click
163
164      There is a div containing the navigation that spans the entire image and lives above of it. If
165      you right-click, you are right clicking this div and not the image. This prevents users from
166      saving the image or using other context menu actions with the image.
167
168      To fix this, when we detect the right mouse button is pressed down, but not yet clicked, we
169      set pointer-events to none on the nav div. This is so that the upcoming right-click event on
170      the next mouseup will bubble down to the image. Once the right-click/contextmenu event occurs
171      we set the pointer events back to auto for the nav div so it can capture hover and left-click
172      events as usual.
173     */
174    this.$nav.on('mousedown', function(event) {
175      if (event.which === 3) {
176        self.$nav.css('pointer-events', 'none');
177
178        self.$lightbox.one('contextmenu', function() {
179          setTimeout(function() {
180              this.$nav.css('pointer-events', 'auto');
181          }.bind(self), 0);
182        });
183      }
184    });
185
186    this.$lightbox.find('.lb-loader, .lb-close').on('click', function() {
187      self.end();
188      return false;
189    });
190  };
191
192  // Show overlay and lightbox. If the image is part of a set, add siblings to album array.
193  Lightbox.prototype.start = function($link) {
194    var self    = this;
195    var $window = $(window);
196
197    $window.on('resize', $.proxy(this.sizeOverlay, this));
198
199    $('select, object, embed').css({
200      visibility: 'hidden'
201    });
202
203    this.sizeOverlay();
204
205    this.album = [];
206    var imageNumber = 0;
207
208    function addToAlbum($link) {
209      self.album.push({
210        link: $link.attr('href'),
211        title: $link.attr('data-title') || $link.attr('title')
212      });
213    }
214
215    // Support both data-lightbox attribute and rel attribute implementations
216    var dataLightboxValue = $link.attr('data-lightbox');
217    var $links;
218
219    if (dataLightboxValue) {
220      $links = $($link.prop('tagName') + '[data-lightbox="' + dataLightboxValue + '"]');
221      for (var i = 0; i < $links.length; i = ++i) {
222        addToAlbum($($links[i]));
223        if ($links[i] === $link[0]) {
224          imageNumber = i;
225        }
226      }
227    } else {
228      if ($link.attr('rel') === 'lightbox') {
229        // If image is not part of a set
230        addToAlbum($link);
231      } else {
232        // If image is part of a set
233        $links = $($link.prop('tagName') + '[rel="' + $link.attr('rel') + '"]');
234        for (var j = 0; j < $links.length; j = ++j) {
235          addToAlbum($($links[j]));
236          if ($links[j] === $link[0]) {
237            imageNumber = j;
238          }
239        }
240      }
241    }
242
243    // Position Lightbox
244    var top  = $window.scrollTop() + this.options.positionFromTop;
245    var left = $window.scrollLeft();
246    this.$lightbox.css({
247      top: top + 'px',
248      left: left + 'px'
249    }).fadeIn(this.options.fadeDuration);
250
251    // Disable scrolling of the page while open
252    if (this.options.disableScrolling) {
253      $('body').addClass('lb-disable-scrolling');
254    }
255
256    this.changeImage(imageNumber);
257  };
258
259  // Hide most UI elements in preparation for the animated resizing of the lightbox.
260  Lightbox.prototype.changeImage = function(imageNumber) {
261    var self = this;
262
263    this.disableKeyboardNav();
264    var $image = this.$lightbox.find('.lb-image');
265
266    this.$overlay.fadeIn(this.options.fadeDuration);
267
268    $('.lb-loader').fadeIn('slow');
269    this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();
270
271    this.$outerContainer.addClass('animating');
272
273    // When image to show is preloaded, we send the width and height to sizeContainer()
274    var preloader = new Image();
275    preloader.onload = function() {
276      var $preloader;
277      var imageHeight;
278      var imageWidth;
279      var maxImageHeight;
280      var maxImageWidth;
281      var windowHeight;
282      var windowWidth;
283
284      $image.attr('src', self.album[imageNumber].link);
285
286      $preloader = $(preloader);
287
288      $image.width(preloader.width);
289      $image.height(preloader.height);
290
291      if (self.options.fitImagesInViewport) {
292        // Fit image inside the viewport.
293        // Take into account the border around the image and an additional 10px gutter on each side.
294
295        windowWidth    = $(window).width();
296        windowHeight   = $(window).height();
297        maxImageWidth  = windowWidth - self.containerPadding.left - self.containerPadding.right - self.imageBorderWidth.left - self.imageBorderWidth.right - 20;
298        maxImageHeight = windowHeight - self.containerPadding.top - self.containerPadding.bottom - self.imageBorderWidth.top - self.imageBorderWidth.bottom - 120;
299
300        // Check if image size is larger then maxWidth|maxHeight in settings
301        if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) {
302          maxImageWidth = self.options.maxWidth;
303        }
304        if (self.options.maxHeight && self.options.maxHeight < maxImageWidth) {
305          maxImageHeight = self.options.maxHeight;
306        }
307
308        // Is the current image's width or height is greater than the maxImageWidth or maxImageHeight
309        // option than we need to size down while maintaining the aspect ratio.
310        if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) {
311          if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) {
312            imageWidth  = maxImageWidth;
313            imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10);
314            $image.width(imageWidth);
315            $image.height(imageHeight);
316          } else {
317            imageHeight = maxImageHeight;
318            imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10);
319            $image.width(imageWidth);
320            $image.height(imageHeight);
321          }
322        }
323      }
324      self.sizeContainer($image.width(), $image.height());
325    };
326
327    preloader.src          = this.album[imageNumber].link;
328    this.currentImageIndex = imageNumber;
329  };
330
331  // Stretch overlay to fit the viewport
332  Lightbox.prototype.sizeOverlay = function() {
333    this.$overlay
334      .width($(document).width())
335      .height($(document).height());
336  };
337
338  // Animate the size of the lightbox to fit the image we are showing
339  Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {
340    var self = this;
341
342    var oldWidth  = this.$outerContainer.outerWidth();
343    var oldHeight = this.$outerContainer.outerHeight();
344    var newWidth  = imageWidth + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right;
345    var newHeight = imageHeight + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom;
346
347    function postResize() {
348      self.$lightbox.find('.lb-dataContainer').width(newWidth);
349      self.$lightbox.find('.lb-prevLink').height(newHeight);
350      self.$lightbox.find('.lb-nextLink').height(newHeight);
351      self.showImage();
352    }
353
354    if (oldWidth !== newWidth || oldHeight !== newHeight) {
355      this.$outerContainer.animate({
356        width: newWidth,
357        height: newHeight
358      }, this.options.resizeDuration, 'swing', function() {
359        postResize();
360      });
361    } else {
362      postResize();
363    }
364  };
365
366  // Display the image and its details and begin preload neighboring images.
367  Lightbox.prototype.showImage = function() {
368    this.$lightbox.find('.lb-loader').stop(true).hide();
369    this.$lightbox.find('.lb-image').fadeIn(this.options.imageFadeDuration);
370
371    this.updateNav();
372    this.updateDetails();
373    this.preloadNeighboringImages();
374    this.enableKeyboardNav();
375  };
376
377  // Display previous and next navigation if appropriate.
378  Lightbox.prototype.updateNav = function() {
379    // Check to see if the browser supports touch events. If so, we take the conservative approach
380    // and assume that mouse hover events are not supported and always show prev/next navigation
381    // arrows in image sets.
382    var alwaysShowNav = false;
383    try {
384      document.createEvent('TouchEvent');
385      alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false;
386    } catch (e) {}
387
388    this.$lightbox.find('.lb-nav').show();
389
390    if (this.album.length > 1) {
391      if (this.options.wrapAround) {
392        if (alwaysShowNav) {
393          this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');
394        }
395        this.$lightbox.find('.lb-prev, .lb-next').show();
396      } else {
397        if (this.currentImageIndex > 0) {
398          this.$lightbox.find('.lb-prev').show();
399          if (alwaysShowNav) {
400            this.$lightbox.find('.lb-prev').css('opacity', '1');
401          }
402        }
403        if (this.currentImageIndex < this.album.length - 1) {
404          this.$lightbox.find('.lb-next').show();
405          if (alwaysShowNav) {
406            this.$lightbox.find('.lb-next').css('opacity', '1');
407          }
408        }
409      }
410    }
411  };
412
413  // Display caption, image number, and closing button.
414  Lightbox.prototype.updateDetails = function() {
415    var self = this;
416
417    // Enable anchor clicks in the injected caption html.
418    // Thanks Nate Wright for the fix. @https://github.com/NateWr
419    if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&
420      this.album[this.currentImageIndex].title !== '') {
421      var $caption = this.$lightbox.find('.lb-caption');
422      if (this.options.sanitizeTitle) {
423        $caption.text(this.album[this.currentImageIndex].title);
424      } else {
425        $caption.html(this.album[this.currentImageIndex].title);
426      }
427      $caption.fadeIn('fast')
428        .find('a').on('click', function(event) {
429          if ($(this).attr('target') !== undefined) {
430            window.open($(this).attr('href'), $(this).attr('target'));
431          } else {
432            location.href = $(this).attr('href');
433          }
434        });
435    }
436
437    if (this.album.length > 1 && this.options.showImageNumberLabel) {
438      var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);
439      this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast');
440    } else {
441      this.$lightbox.find('.lb-number').hide();
442    }
443
444    this.$outerContainer.removeClass('animating');
445
446    this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() {
447      return self.sizeOverlay();
448    });
449  };
450
451  // Preload previous and next images in set.
452  Lightbox.prototype.preloadNeighboringImages = function() {
453    if (this.album.length > this.currentImageIndex + 1) {
454      var preloadNext = new Image();
455      preloadNext.src = this.album[this.currentImageIndex + 1].link;
456    }
457    if (this.currentImageIndex > 0) {
458      var preloadPrev = new Image();
459      preloadPrev.src = this.album[this.currentImageIndex - 1].link;
460    }
461  };
462
463  Lightbox.prototype.enableKeyboardNav = function() {
464    $(document).on('keyup.keyboard', $.proxy(this.keyboardAction, this));
465  };
466
467  Lightbox.prototype.disableKeyboardNav = function() {
468    $(document).off('.keyboard');
469  };
470
471  Lightbox.prototype.keyboardAction = function(event) {
472    var KEYCODE_ESC        = 27;
473    var KEYCODE_LEFTARROW  = 37;
474    var KEYCODE_RIGHTARROW = 39;
475
476    var keycode = event.keyCode;
477    var key     = String.fromCharCode(keycode).toLowerCase();
478    if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) {
479      this.end();
480    } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) {
481      if (this.currentImageIndex !== 0) {
482        this.changeImage(this.currentImageIndex - 1);
483      } else if (this.options.wrapAround && this.album.length > 1) {
484        this.changeImage(this.album.length - 1);
485      }
486    } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) {
487      if (this.currentImageIndex !== this.album.length - 1) {
488        this.changeImage(this.currentImageIndex + 1);
489      } else if (this.options.wrapAround && this.album.length > 1) {
490        this.changeImage(0);
491      }
492    }
493  };
494
495  // Closing time. :-(
496  Lightbox.prototype.end = function() {
497    this.disableKeyboardNav();
498    $(window).off('resize', this.sizeOverlay);
499    this.$lightbox.fadeOut(this.options.fadeDuration);
500    this.$overlay.fadeOut(this.options.fadeDuration);
501    $('select, object, embed').css({
502      visibility: 'visible'
503    });
504    if (this.options.disableScrolling) {
505      $('body').removeClass('lb-disable-scrolling');
506    }
507  };
508
509  return new Lightbox();
510}));

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.