PageSourceSearch

https://apartel-resorts.com/assets/js/jquery.littlelightbox.js

js apartel-resorts.com collected 2026-10-08 20:30:51 UTC 22,666 bytes, 923 lines download raw bytes

1/*!
2 * littleLightBox - jQuery Plugin
3 * version: 0.9 (Tues, 2 Aug 2016)
4 * requires jQuery v1.7 or later
5 *
6 *
7 * Copyright 2016 Sherry Tao - [email protected]
8 *
9 */
10(function(win, doc, $, undefined) {
11 	"use strict";
12 	var window = $(win),
13 		document = $(doc),
14 		isQuery	= function(obj) {
15			return obj && obj.hasOwnProperty && obj instanceof $;
16		},
17 		lightbox = $.littleLightBox = function () {
18			lightbox.open.apply( this, arguments );
19		};
20
21 	$.extend(lightbox, {
22 		defaults: {
23 				helpers: {
24
25 				},
26 				tpl: {
27 					wrap: '<div class="lightbox-wrap"><div class="lightbox-skin"><div class="lightbox-outer"><div class="lightbox-inner" style="overflow: hidden;"></div></div></div></div>',
28 					img: '<img class="lightbox-image" src="{href}" style="width:100%;height:100%;"/>',
29 					loading: '<div class="lightbox-loading"><div></div></div>',
30 					closeBtn: '<div class="lightbox-closeBtn"></div>',
31 					prevBtn: '<div class="lightbox-prevBtn lightbox-nav"><span></span></div>',
32 					nextBtn: '<div class="lightbox-nextBtn lightbox-nav"><span></span></div>',
33 				},
34 				padding: 15,
35 				minWidth: 200,
36 				minHeight: 200,
37 				maxWidth: 9999,
38 				maxHeight: 9999,
39 				wrapRatio: 0.8,
40 				top: 0.5,
41 				left: 0.5,
42 				loop: false,
43
44 				// Open Animate.
45 				openMethod: 'fadeIn', // including 'changeIn','fadeIn', 'elasticIn'
46 				openDirect: 'down', // Avaliable if openMethod is 'changeIn', 'down', 'up', 'left', 'right' is avaliable.
47 				openSpeed: 400,
48
49 				distance: 200, // Avaliable if openMethod is 'changeIn', 200 and 'hide' is avaliable.
50
51 				// Close Animate.
52 				closeMethod: 'fadeOut',
53 				closeDirect: 'up',
54 				closeDistance: 'hide',
55 				closeSpeed: 400,
56
57 				// Change Animate.
58 				prevMethod: 'changeOut',
59 				nextMethod: 'changeIn',
60 				changeSpeed: 600,
61
62 				direction: {
63 					next: 'left',
64 					prev: 'right'
65 				},
66
67 				// key settings
68  				keys: {
69  					close: [27, 46], // esc key & delete key
70  					next: {
71  						13: 'left', // enter key
72  						39: 'left', // right arrow
73  						68: 'left', // D key
74  						40: 'up',   // down arrow
75  						34: 'up',   // pgdn key
76  						83: 'up',   // S key
77  					},
78  					prev: {
79  						8: 'right',  // backspace key
80  						37: 'right', // left arrow
81  						65: 'right', // A key
82  						38: 'down',  // up arrow
83  						33: 'down',  // pgup key
84  						87: 'down',  // W key
85  					},
86  				},
87 			},
88 		helpers: {},
89 		isOpen: false,
90 		isClosing: false,
91 		isDisplay: false,
92
93 		doUpdate: null,
94 		coming: null,
95 		current: null,
96
97 		open: function(group, options) {
98 			// prevent $.littleLightBox() or new lightbox().
99 			if (!group) {
100				return;
101			}
102
103 			this.opts = $.extend({}, this.defaults, options || {});
104 			
105 			if (options && options.keys) {
106  				$.extend(this.opts, this.defaults.keys, options.keys);
107  			}
108
109 			// Normalize group
110 			if (!$.isArray(group)) {
111 				group = isQuery(group) ? group.get() : [group];
112 			}
113
114 			// Get images information from group ( caption, href, index in group)
115 			$.each(group, function(index, element) {
116 				var obj = {},
117 					text = '',
118 					href = '',
119 					idx = 0;
120
121 				idx = index + 1;
122
123 				if (element.nodeType) {
124 					element = $(element);
125 				}
126
127 				if (isQuery(element)) {
128 					href = element.data('lightbox-href') || element.attr('href');
129 					text = element.data('lightbox-title') || element.attr('title') || '';
130 				}
131
132 				href || (element.attr('src') && (href = element.attr('src'))) || (href = element.find('img[src]').attr('src'));
133
134 				if (!href) {
135 					return false;
136 				}
137
138 				$.extend(obj, {
139 					index: idx,
140 					href: href,
141 					text: text,
142 					element: element,
143 				});
144
145 				group[index] = obj;
146 			});
147
148 			this.group = group;
149
150 			this._run(this.opts.index);
151 		},
152
153 		next: function(direct) {
154 			if (lightbox.isClosing) {
155 				return ;
156 			}
157
158 			var current = lightbox.current,
159 				index,
160 				direction;
161
162 			if (current) {
163 				index = current.index;
164 				direction = (direct && $.type(direct) === "string") ? direct : current.direction.next;
165
166 				this._jump(index + 1, direction);
167 			}
168 		},
169
170 		prev: function(direct) {
171 			if (lightbox.isClosing) {
172 				return ;
173 			}
174 			var current = lightbox.current,
175 				index,
176 				direction;
177
178 			if (current) {
179 				index = current.index;
180 				direction = (direct && $.type(direct) === "string") ? direct : current.direction.prev;
181
182 				this._jump(index - 1, direction);
183 			}
184 		},
185
186 		_jump: function(index, direction) {
187 			if (!this.isDisplay)
188  				return ;
189
190 			var imageNum = this.group.length,
191 				index = index - 1;
192 			
193 			lightbox.direction = direction;
194 			this._hideLoading();
195
196 			if (this.opts.loop) {
197 				// Get Really index
198 				if (index < 0) {
199 					index = imageNum + (index % imageNum);
200 				}
201 				index = index % imageNum;
202 			}
203
204 			this._run(index);
205 		},
206
207 		_run: function(index) {
208
209 			var obj = (this.group)[index],
210 				coming = $.extend({}, this.opts, obj);	
211
212 			if (!obj) {
213  				return ;
214  			}	
215
216 			if (!this.isOpen) {
217 				this.helpers.mask.open(this.opts.helpers.mask || {});			
218 			}
219 			
220 			// prepare wrap struct
221 			this.wrap = coming.wrap = $(coming.tpl.wrap).appendTo(coming.parent || 'body').hide();
222
223 			if ($.type(coming.padding) === 'number') {
224 				coming.padding = [coming.padding, coming.padding, coming.padding, coming.padding];
225 			}
226 			
227 			$.extend(coming, {
228 				skin: $('.lightbox-skin', coming.wrap),
229 				outer: $('.lightbox-outer', coming.wrap),
230 				inner: $('.lightbox-inner', coming.wrap),
231 				loading: null,
232 			});
233
234 			coming.inner.width(0).height(0);
235 			this.width = coming.padding[1] + coming.padding[3];
236 			this.height = coming.padding[0] + coming.padding[2];
237
238 			coming.skin.css('padding', coming.padding[0] + 'px '
239 									+ coming.padding[1] + 'px '
240 									+ coming.padding[2] + 'px '
241 									+ coming.padding[3] + 'px');
242
243 			this._setPosition(coming.wrap, false);
244
245 			this.coming = coming;
246
247 			this._loadImage();
248 		},
249
250 		_loadImage: function() {
251 			var image = new Image(),
252 				that = this;
253 			image.src = this.coming.href;
254
255 			image.onload = function () {
256 				that.coming.width = this.width;
257 				that.coming.height = this.height;
258
259 				that._afterLoad();
260 			};
261
262 			if (!image.complete) {
263 				this._showLoading();
264 			}
265 		},
266
267 		_showLoading: function() {
268 			var that = this,
269 				pos = this._getPosition();
270 			
271 			if (this.coming.loading) {
272 				return ;
273 			}
274
275 			this._hideLoading();
276 			this.coming.loading = $(this.coming.tpl.loading).appendTo(this.coming.parent || 'body');
277 			this.coming.loading.css({
278 				top: window.height() * 0.5 + pos.scrollTop,
279 				left: window.width() * 0.5 + pos.scrollLeft,
280 			});
281 		},
282
283 		_hideLoading: function() {
284 			if (this.coming && this.coming.loading) {
285 				this.coming.loading.stop().off('.loading').remove();
286 				this.coming.loading = null;
287 			}
288 		},
289
290 		_afterLoad: function() {
291 			this._hideLoading();
292 			var href,
293 				current = this.coming,
294 				previous = this.current,
295 				content;
296
297 			$.extend(lightbox, {
298 				wrap: current.wrap,
299 				skin: current.skin,
300 				outer: current.outer,
301 				inner: current.inner,
302 				current: current,
303 				previous: previous,
304 				coming: null,
305 			});
306
307 			this.unbindEvent();
308
309 			if (previous) {
310 				this.width = 'auto';
311 				this.height = 'auto';
312
313 				this.helpers.title.hide();
314 				previous.wrap.stop(true, true).find('.lightbox-nav, .lightbox-closeBtn').remove();
315 			}
316
317 			href = current.href;
318 			content = current.tpl.img.replace(/\{href\}/g, href);
319 			$(content).appendTo(current.inner);
320
321 			// create title helper.
322
323 			var titleOpts = $.extend({'text': current.text,
324 									'idxInfo': '( ' + current.index + ' of ' + this.group.length +' )'},
325 									current.helpers.title);
326 			this.helpers.title.show(titleOpts);
327
328 			current.closeBtn = $(current.tpl.closeBtn).appendTo(current.skin);
329 			
330 			current.wrap.show();
331
332 			if (current.index > 1 || this.opts.loop) {
333 				current.prevBtn = $(current.tpl.prevBtn).appendTo(current.skin);
334 			}
335 			
336 			if (current.index < this.group.length || this.opts.loop) {
337 				current.nextBtn = $(current.tpl.nextBtn).appendTo(current.skin);
338 			}
339
340 			this.bindEvent();
341 			
342 			this._setDimension(false);
343 			this._setPosition(this.wrap, false);
344
345 			// Transition
346 			if (previous) {
347 				this.isDisplay = false;
348 				this.trasition[previous.prevMethod]();
349 			}
350 			this.trasition[this.isOpen ? current.nextMethod : current.openMethod]();
351 		},
352
353 		unbindEvent: function() {
354 			var current = this.current;
355 
356  			if (current && isQuery(current.wrap)) {
357  				current.wrap.off('.btn');
358  			}
359
360  			window.off('.lb');
361  			document.off('.lb');
362 		},
363
364 		bindEvent: function() {
365 			var current = lightbox.current,
366 				keys;
367 
368  			if (!current) {
369  				return ;
370  			}
371
372 			window.off('.lb').on('resize.lb', this.update);
373
374 			// Binding Key Board Event
375 			keys = current.keys;
376 
377  			if (keys) {
378  				document.on('keydown.lb', function(event) {
379  					var key = event.which || event.keyCode;
380 
381  					$.each(keys, function(name, value) {
382  						// test close key
383  						if ($.inArray(key, value) > -1 && !lightbox.coming) {
384  							lightbox[name]();
385  							return false;
386  						}
387  						// test nav key
388  						if (lightbox.group.length > 1 && value[key] !== undefined ) {
389  							lightbox[name](value[key]);
390  							return false;
391  						}
392  					});
393 
394  					event.preventDefault();
395  				});
396  			}
397
398 		},
399
400 		update: function() {
401 			var current = lightbox.current,
402 				doUpdate = lightbox.doUpdate;
403
404 			if (!lightbox.isOpen || doUpdate) {
405 				return ;
406 			}
407
408 			lightbox.doUpdate = setTimeout(function() {
409 				if (current && !lightbox.isClosing) {
410 					lightbox.trigger('onUpdate');
411
412 					lightbox._setDimension(true);
413 					lightbox._setPosition(current.wrap, true);
414
415 					lightbox.doUpdate = null;
416 				}
417 			}, 300);
418 		},
419
420 		trigger: function(eventType, obj) {
421 			var obj = obj || lightbox;
422
423 			if (obj) {
424 				if ($.isFunction(obj[eventType])) {
425 					obj[eventType].apply(obj, Array.prototype.slice.call(arguments, 1));
426 				}
427
428 				$.each(obj.helpers, function(index, elem) {
429 					if (elem && $.isFunction(elem[eventType])) {
430 						elem[eventType].apply(elem, Array.prototype.slice.call(arguments, 1));
431 					}
432 				}); 
433 			}
434
435 			document.trigger(eventType);
436 		},
437
438 		_setDimension: function(isAnimate) {
439 			var that = this, 
440 				width,
441 				height,
442 				winWidth,
443 				winHeight,
444 				minWidth,
445 				minHeight,
446 				maxWidth,
447 				maxHeight,
448 				innerWidth,
449 				innerHeight,
450
451 				ratio,
452 				aspectRatioImage;
453
454 			ratio = this.current.wrapRatio;
455 			winWidth = window.width() * ratio;
456 			winHeight = window.height() * ratio;
457 			minWidth = this.current.minWidth;
458 			minHeight = this.current.minHeight;
459 			maxWidth = this.current.maxWidth;
460 			maxHeight = this.current.maxHeight;
461 			width = this.current.width + this.current.padding[1] + this.current.padding[3];
462 			height = this.current.height + this.current.padding[0] + this.current.padding[2];
463
464 			aspectRatioImage = this.current.width * 1.0 / this.current.height;
465
466 			maxWidth = Math.min(winWidth, maxWidth);
467 			maxHeight = Math.min(winHeight, maxHeight);
468
469 			if (width > maxWidth) {
470 				width = maxWidth;
471 				height = width / aspectRatioImage;
472 			}
473 			if (height > maxHeight) {
474 				height = maxHeight;
475 				width = height * aspectRatioImage;
476 			}
477 			if (width < minWidth) {
478 				width = minWidth;
479 				height = width / aspectRatioImage;
480 			}
481 			if (height < minHeight) {
482 				height = minHeight;
483 				width = height * aspectRatioImage;
484 			}
485
486 			this.innerWidth = innerWidth = width - this.current.padding[1] - this.current.padding[3];
487 			this.innerHeight = innerHeight = height - this.current.padding[0] - this.current.padding[2];
488
489 			this.width = width;
490 			this.height = height;
491
492 			if (isAnimate) {
493 				this.inner.animate({
494 					width: innerWidth,
495 					height: innerHeight,
496 				});
497 			} else {
498 				this.inner.width(innerWidth).height(innerHeight);
499 			}
500 			
501 		},
502
503 		_setPosition: function(obj, isAnimate) {
504 			var pos = this._getPosition();
505 			if (isAnimate) {
506 				obj.animate(pos);
507 			} else {
508 				obj.css({
509 					'top': pos.top,
510 					'left': pos.left,
511 				});
512 			} 
513 		},
514
515 		_getPosition: function() {
516 			var pos = {
517 					'scrollTop': window.scrollTop(),
518 					'scrollLeft': window.scrollLeft(),
519 				};
520
521 			pos.top = (window.height() - lightbox.height) * this.opts.top + pos.scrollTop;
522 			pos.left = (window.width() - lightbox.width) * this.opts.left + pos.scrollLeft;
523
524 			return pos;
525 		},
526
527 		_afterLoadIn: function() {
528 			lightbox.isOpen = true;
529 			// load prev, next and close btn.
530 			var current = lightbox.current;
531 			lightbox.index = current.index;
532 			
533 			if (current.closeBtn) {
534 				current.closeBtn.off('.btn').on('click.btn', function(event) {
535 					event.preventDefault();
536 					lightbox.close();
537 				});
538 			}
539 			
540 			if (current.prevBtn) {
541 				current.prevBtn.off('.btn').on('click.btn', function(event) {
542 					event.preventDefault();
543 					lightbox.prev();
544 				});
545 			}
546 			
547 			if (current.nextBtn) {
548 				current.nextBtn.off('.btn').on('click.btn', function(event) {
549 					event.preventDefault();
550 					lightbox.next();
551 				});
552 			}
553
554  			lightbox.isDisplay = true;
555 		},
556
557 		_afterLoadOut: function() {
558 			lightbox.isOpen = !lightbox.isClosing;
559 			lightbox.isClosing = false;
560
561 			if (lightbox.isOpen && lightbox.previous) {
562 				lightbox.previous.wrap.remove();
563 			} else {
564 				lightbox.wrap.remove();
565 				lightbox.helpers.mask.close();
566 				lightbox.helpers.title.hide();
567
568 				// initial lightbox status
569 				lightbox.mask = null;
570 				lightbox.doUpdate = null;
571 				lightbox.current = null;
572 				lightbox.coming = null;
573 			}
574 		},
575
576 		close: function() {
577 			if (this.isOpen && !this.isClosing) {
578 				this.isClosing = true;
579 				lightbox.isDisplay = false;
580  				this.unbindEvent();
581  				this._hideLoading();
582 				this.trasition[this.opts.closeMethod]();
583 			}
584 		}
585 	});
586
587	/* Lightbox trasition */
588	lightbox.trasition = {
589		getCenter: function() {
590
591			var pos = {
592				w: window.width(),
593				h: window.height(),
594				y: window.scrollTop(),
595				x: window.scrollLeft(),
596			}
597			return pos;
598		},
599
600		fadeIn: function() {
601			var startPos = lightbox._getPosition(),
602				endPos = $.extend({opacity: 1}, startPos),
603				speed = lightbox.isOpen ? lightbox.opts.changeSpeed : lightbox.opts.openSpeed;
604
605			startPos.opacity = 0.1;
606
607			lightbox.wrap.stop(true, true).css(startPos).animate(endPos, {
608				duration: speed,
609				complete: lightbox._afterLoadIn,
610			});
611		},
612
613		elasticIn: function() {
614			var offsetTopRatio = 0.9,
615				offsetLeftRatio = 0.8,
616				pos = this.getCenter(),
617				endSize = {width: lightbox.innerWidth,
618						  height: lightbox.innerHeight,
619						  },
620				startWidth = lightbox.opts.minWidth,
621				startHeight = lightbox.opts.minHeight,
622
623				startSize = {width: startWidth,
624							height: startHeight,
625							},
626				endPos = $.extend({opacity: 1}, lightbox._getPosition()),
627				startPos = {opacity: 0,
628						    top: (pos.h * offsetTopRatio) * lightbox.opts.top + pos.y,
629						    left: (pos.w * offsetLeftRatio) * lightbox.opts.left + pos.x},
630				speed = lightbox.isOpen ? lightbox.opts.changeSpeed : lightbox.opts.openSpeed;
631
632			lightbox.inner.stop(true, true).css(startSize).animate(endSize,{
633				duration: speed,
634			});
635
636			lightbox.wrap.stop(true, true).css(startPos).animate(endPos, {
637				duration: speed,
638				complete: lightbox._afterLoadIn,
639			});
640		},
641
642		changeIn: function() {
643			var field,
644				current = lightbox.current,
645				direct = lightbox.isOpen ? lightbox.direction : current.openDirect,
646				distance = lightbox.opts.openDistance === 'hide' ? 'hide' : 200,
647				speed = lightbox.isOpen ? lightbox.opts.changeSpeed : lightbox.opts.openSpeed,
648				startPos = lightbox._getPosition(),
649				endPos = {opacity: 1};
650
651			field = direct === 'down' || direct === 'up' ? 'top' : 'left';
652			startPos.opacity = 0.1;
653
654			if (distance === 'hide') {
655				distance = field === 'top' ? startPos.top : startPos.left;
656			} else {
657				distance = field === 'top' ? Math.min(distance, startPos.top) : Math.min(distance, startPos.left);
658			}
659
660			if (direct === 'down' || direct === 'right') {
661				startPos[field] = (startPos[field] - distance) + 'px';
662				endPos[field] = '+=' + distance + 'px';
663			} else {
664				startPos[field] = (startPos[field] + distance) + 'px';
665				endPos[field] = '-=' + distance + 'px';
666			}
667
668			current.wrap.stop(true, true).css(startPos).animate(endPos, {
669				duration: speed,
670				complete: lightbox._afterLoadIn,
671			});
672		},
673
674		fadeOut: function() {
675			var previous = lightbox.previous,
676				target = lightbox.isClosing ? lightbox.wrap : previous.wrap,
677				speed = lightbox.isClosing ? lightbox.opts.changeSpeed : lightbox.opts.closeSpeed;
678
679			target.stop(true, true).animate({opacity: 0}, {
680				duration: speed,
681				complete: lightbox._afterLoadOut,
682			});
683		},
684
685		elasticOut: function() {
686			var offsetTopRatio = 0.9,
687 				offsetLeftRatio = 0.8,
688 				previous = lightbox.previous,
689				target = lightbox.isClosing ? lightbox.wrap : previous.wrap,
690				pos = this.getCenter(),
691				speed = lightbox.isClosing ? lightbox.opts.changeSpeed : lightbox.opts.closeSpeed,
692				endPos = {
693					opacity: 0,
694					top: (pos.h * offsetTopRatio) * lightbox.opts.top + pos.y,
695 					left: (pos.w * offsetLeftRatio) * lightbox.opts.left + pos.x,
696				},
697				endSize = {
698					width: 0,
699					height: 0,
700				};
701
702			target.find('.lightbox-title').fadeOut();
703			target.find('.lightbox-inner').stop(true, true).animate(endSize,{
704				duration: speed,
705			});
706
707			target.stop(true, true).animate(endPos, {
708				duration: speed,
709				complete: lightbox._afterLoadOut,
710			});
711		},
712
713		changeOut: function() {
714			var field,
715				previous = lightbox.previous,
716				target = lightbox.isClosing ? lightbox.wrap : previous.wrap, 
717				direct = lightbox.isClosing ? lightbox.opts.closeDirect : lightbox.direction,
718				distance = lightbox.isClosing ? (lightbox.opts.closeDistance === 'hide' ? 'hide' : 200) : lightbox.opts.distance,
719				speed = lightbox.isClosing ? lightbox.opts.changeSpeed : lightbox.opts.closeSpeed,
720				
721				startPos = lightbox._getPosition(),
722				endPos = {opacity: 0.1};
723
724			field = direct === 'down' || direct === 'up' ? 'top' : 'left';
725
726			if (distance === 'hide') {
727				distance = field === 'top' ? startPos.top : startPos.left;
728			} else {
729				distance = field === 'top' ? Math.min(distance, startPos.top) : Math.min(distance, startPos.left);
730			}
731
732			if (direct === 'down' || direct === 'right') {
733				endPos[field] = '+=' + distance + 'px';
734			} else {
735				endPos[field] = '-=' + distance + 'px';
736			}
737
738			target.stop(true, true).animate(endPos, {
739				duration: speed,
740				complete: lightbox._afterLoadOut,
741			});
742		},
743	}
744
745 	/* Lightbox Mask helper */
746 	lightbox.helpers.mask = {
747 		defaults: {
748 			closeClick: true,
749 			speed: 200,
750 			fix: true,
751 		},
752 		tpl: '<div class="lightbox-mask" style="width: 100%; height: 100%;"></div>',
753 		mask: null,
754 		parent: 'body',
755
756 		create: function(opts) {
757 			opts = opts || {};
758 			this.opts = $.extend({}, this.defaults, opts);
759
760 			if (this.mask) {
761 				this.close();
762 			}
763
764 			this.mask = $(this.tpl).appendTo(this.parent);
765
766 		},
767 		open: function(opts) {
768 			var that = this;
769
770 			if (!this.mask) {
771 				this.create(opts);
772 			}
773
774 			this.mask.width(document.width()).height(document.height());
775
776 			if (this.opts.closeClick) {
777 				this.mask.off('.mask').on('click.mask', function(e) {
778 					if ($(e.target).hasClass('lightbox-mask')) {
779 						if (lightbox.isOpen) {
780 							lightbox.close();
781 						} else {
782 							that.close();
783 						}
784 					}
785 				});
786 			}
787
788 			this.mask.fadeIn(that.opts.speed);
789 		},
790 		close: function() {
791 			var that = this;
792 			if (!lightbox.isClosing) {
793 				lightbox._hideLoading();
794				that.mask.off('.mask').fadeOut(that.opts.speed, function() {
795					that.mask.remove();
796					that.mask = null;
797				});
798 			}
799 		},
800 		
801 		onUpdate: function() {
802 			if (this.mask) {
803 				this.update();
804 			}
805 		},
806
807 		update: function() {
808 			this.mask.width(document.width()).height(document.height());
809 		},
810 	};
811
812 	/* Lightbox Title helper */
813 	lightbox.helpers.title = {
814 		defaults: {
815 			position: 'bottom', // title position: top, bottom.
816 			type: 'over', // title type: inside, over.
817 			text: 'photo title',
818 			idxInfo: 'image 0 of 0',
819 		},
820 		title: null,
821 		isExist: false,
822
823 		create: function(opts) {
824 			var that = this,
825 				current = lightbox.current;
826 			this.opts = $.extend({}, this.defaults, opts || {});
827
828 			if (this.title) {
829 				this.title.stop(true, true).remove();
830 			}
831
832 			
833 			// Get the wrap of title helper.
834 			switch (this.opts.type) {
835 				case 'inside':
836 					this.parent = lightbox.skin;
837 					this.title = $('<div class="lightbox-title lightbox-title-' + this.opts.type + '"><p>' + this.opts.text + '</p></div>');
838 				break;
839 				case 'over':
840 				default: 
841 					this.parent = lightbox.outer;
842 					this.title = $('<div class="lightbox-title lightbox-title-' + this.opts.type + '"><p>' + this.opts.text + '</p>' + '<span>' + this.opts.idxInfo + '</span></div>');
843 				break;
844 			}
845
846 			this.title[this.opts.position === 'bottom' ? 'appendTo' : 'prepe
846ndTo'](this.parent);
847 			this.isExist = true; 			
848
849 		},
850 		show: function(opts) {
851 			var that = this;
852 			
853 			this.beforeShow(opts);
854
855 			if (!this.isExist) {
856 				this.create(opts);
857 			}
858
859 			this.title.fadeIn();
860
861 			this.afterShow(opts);
862
863 			return this;
864 		},
865 		hide: function() {
866 			var that = this;
867
868 			if (this.isExist) {
869 				this.isExist = false;
870
871 				this.title.fadeOut(function() {
872 					that.title.remove();
873 					that.title = null;
874 				});
875 			}
876
877 			return this;
878 		},
879 		beforeShow: function(opts) {
880 			$.noop;
881 		},
882 		afterShow: function(opts) {
883 			$.noop;
884 		}
885 	};
886
887 	$.fn.littleLightBox = function(opts) {
888 		opts = opts ? opts : {};
889 		var that = $(this),
890 			index = 0,
891 			selector = this.selector || '',
892 			run = function(e) {
893 				var what = $(this).blur(), idx = 0;
894 				var relType = opts.groupType ? opts.groupType : 'data-littlelightbox-group',
895 					relValue = what.attr(relType);
896
897 				if (!relValue) {
898 					relType = 'rel';
899 					relValue = what.attr(relType);
900 				}
901
902 				// get all images from group 'relValue'.
903 				what = selector.length ? $(selector) : that;
904 				what = what.filter('[' + relType + '=' + relValue + ']');
905 				
906 				if (what.length === 0) {
907  					what = $(this);
908  				}
909
910  				idx = what.index(this);
911 				opts.index = idx;
912
913 				lightbox.open(what, opts);
914
915 				e.preventDefault();
916 			};
917
918 		$(selector).off('click').on('click', run);
919
920 		return this;
921 	};
922
923 }(window, document, jQuery));

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.