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