PageSourceSearch

https://www.irta.cat/wp-content/themes/irta/resources/v1/js/lightcase.js?ver=20260924085851

js irta.cat collected 2026-09-24 08:59:30 UTC 52,703 bytes, 1,912 lines download raw bytes

1/*
2 * Lightcase - jQuery Plugin
3 * The smart and flexible Lightbox Plugin.
4 *
5 * @author		Cornel Boppart <[email protected]>
6 * @copyright	Author
7 *
8 * @version		2.5.0 (11/03/2018)
9 */
10
11;(function ($) {
12
13	'use strict';
14
15	var _self = {
16		cache: {},
17
18		support: {},
19
20		objects: {},
21		
22		dimensions: {},
23
24		/**
25		 * Initializes the plugin
26		 *
27		 * @param	{object}	options
28		 * @return	{object}
29		 */
30		init: function (options) {
31			return this.each(function () {
32				$(this).unbind('click.lightcase').bind('click.lightcase', function (event) {
33					event.preventDefault();
34					$(this).lightcase('start', options);
35				});
36			});
37		},
38
39		/**
40		 * Starts the plugin
41		 *
42		 * @param	{object}	options
43		 * @return	{void}
44		 */
45		start: function (options) {
46			_self.origin = lightcase.origin = this;
47
48			_self.settings = lightcase.settings = $.extend(true, {
49				idPrefix: 'lightcase-',
50				classPrefix: 'lightcase-',
51				attrPrefix: 'lc-',
52				transition: 'elastic',
53				transitionOpen: null,
54				transitionClose: null,
55				transitionIn: null,
56				transitionOut: null,
57				cssTransitions: true,
58				speedIn: 250,
59				speedOut: 250,
60				width: null,
61				height: null,
62				maxWidth: 1000,
63				maxHeight: null,
64				forceWidth: false,
65				forceHeight: false,
66				liveResize: true,
67				fullScreenModeForMobile: true,
68				mobileMatchExpression: /(iphone|ipod|ipad|android|blackberry|symbian)/,
69				disableShrink: false,
70				fixedRatio: true,
71				shrinkFactor: .75,
72				overlayOpacity: .9,
73				slideshow: false,
74				slideshowAutoStart: true,
75				breakBeforeShow: false,
76				timeout: 5000,
77				swipe: true,
78				useKeys: true,
79				useCategories: true,
80				useAsCollection: false,
81				navigateEndless: true,
82				closeOnOverlayClick: true,
83				title: null,
84				caption: null,
85				showTitle: true,
86				showCaption: true,
87				showSequenceInfo: false,
88				inline: {
89					width: '820',
90					height: 'auto'
91				},
92				ajax: {
93					width: 'auto',
94					height: 'auto',
95					type: 'get',
96					dataType: 'html',
97					data: {}
98				},
99				iframe: {
100					width: 800,
101					height: 'auto',
102					frameborder: 0
103				},
104				flash: {
105					width: 400,
106					height: 205,
107					wmode: 'transparent'
108				},
109				video: {
110					width: 400,
111					height: 225,
112					poster: '',
113					preload: 'auto',
114					controls: true,
115					autobuffer: true,
116					autoplay: true,
117					loop: false
118				},
119				attr: 'data-rel',
120				href: null,
121				type: null,
122				typeMapping: {
123					'image': 'jpg,jpeg,gif,png,bmp',
124					'flash': 'swf',
125					'video': 'mp4,mov,ogv,ogg,webm',
126					'iframe': 'html,php',
127					'ajax': 'json,txt',
128					'inline': '#'
129				},
130				errorMessage: function () {
131					return '<p class="' + _self.settings.classPrefix + 'error">' + _self.settings.labels['errorMessage'] + '</p>';
132				},
133				labels: {
134					'errorMessage': 'Source could not be found...',
135					'sequenceInfo.of': ' of ',
136					'close': 'Close',
137					'navigator.prev': 'Prev',
138					'navigator.next': 'Next',
139 					'navigator.play': 'Play',
140					'navigator.pause': 'Pause'
141				},
142				markup: function () {
143					_self.objects.body.append(
144						_self.objects.overlay = $('<div id="' + _self.settings.idPrefix + 'overlay"></div>'),
145						_self.objects.loading = $('<div id="' + _self.settings.idPrefix + 'loading" class="' + _self.settings.classPrefix + 'icon-spin"></div>'),
146						_self.objects.case = $('<div id="' + _self.settings.idPrefix + 'case" aria-hidden="true" role="dialog"></div>')
147					);
148					_self.objects.case.after(
149						_self.objects.close = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-close"><span>' + _self.settings.labels['close'] + '</span></a>'),
150						_self.objects.nav = $('<div id="' + _self.settings.idPrefix + 'nav"></div>')
151					);
152					_self.objects.nav.append(
153						_self.objects.prev = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-prev"><span>' + _self.settings.labels['navigator.prev'] + '</span></a>').hide(),
154						_self.objects.next = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-next"><span>' + _self.settings.labels['navigator.next'] + '</span></a>').hide(),
155						_self.objects.play = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-play"><span>' + _self.settings.labels['navigator.play'] + '</span></a>').hide(),
156						_self.objects.pause = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-pause"><span>' + _self.settings.labels['navigator.pause'] + '</span></a>').hide()
157					);
158					_self.objects.case.append(
159						_self.objects.content = $('<div id="' + _self.settings.idPrefix + 'content"></div>'),
160						_self.objects.info = $('<div id="' + _self.settings.idPrefix + 'info"></div>')
161					);
162					_self.objects.content.append(
163						_self.objects.contentInner = $('<div class="' + _self.settings.classPrefix + 'contentInner"></div>')
164					);
165					_self.objects.info.append(
166						_self.objects.sequenceInfo = $('<div id="' + _self.settings.idPrefix + 'sequenceInfo"></div>'),
167						_self.objects.title = $('<h4 id="' + _self.settings.idPrefix + 'title"></h4>'),
168						_self.objects.caption = $('<p id="' + _self.settings.idPrefix + 'caption"></p>')
169					);
170				},
171				onInit: {},
172				onStart: {},
173				onBeforeCalculateDimensions: {},
174				onAfterCalculateDimensions: {},
175				onBeforeShow: {},
176				onFinish: {},
177				onResize: {},
178				onClose: {},
179				onCleanup: {}
180			},
181			options,
182			// Load options from data-lc-options attribute
183			_self.origin.data ? _self.origin.data('lc-options') : {});
184
185			_self.objects.document = $('html');
186			_self.objects.body = $('body');
187
188			// Call onInit hook functions
189			_self._callHooks(_self.settings.onInit);
190
191			_self.objectData = _self._setObjectData(this);
192
193			_self._addElements();
194			_self._open();
195
196			_self.dimensions = _self.getViewportDimensions();
197		},
198
199		/**
200		 * Getter method for objects
201		 *
202		 * @param	{string}	name
203		 * @return	{object}
204		 */
205		get: function (name) {
206			return _self.objects[name];
207		},
208
209		/**
210		 * Getter method for objectData
211		 *
212		 * @return	{object}
213		 */
214		getObjectData: function () {
215			return _self.objectData;
216		},
217
218		/**
219		 * Sets the object data
220		 *
221		 * @param	{object}	object
222		 * @return	{object}	objectData
223		 */
224		_setObjectData: function (object) {
225		 	var $object = $(object),
226				objectData = {
227				this: $(object),
228				title: _self.settings.title || $object.attr(_self._prefixAttributeName('title')) || $object.attr('title'),
229				caption: _self.settings.caption || $object.attr(_self._prefixAttributeName('caption')) || $object.children('img').attr('alt'),
230				url: _self._determineUrl(),
231				requestType: _self.settings.ajax.type,
232				requestData: _self.settings.ajax.data,
233				requestDataType: _self.settings.ajax.dataType,
234				rel: $object.attr(_self._determineAttributeSelector()),
235				type: _self._verifyDataType(_self._determineUrl()),
236				isPartOfSequence: _self.settings.useAsCollection || _self._isPartOfSequence($object.attr(_self.settings.attr), ':'),
237				isPartOfSequenceWithSlideshow: _self._isPartOfSequence($object.attr(_self.settings.attr), ':slideshow'),
238				currentIndex: $(_self._determineAttributeSelector()).index($object),
239				sequenceLength: $(_self._determineAttributeSelector()).length
240			};
241
242			// Add sequence info to objectData
243			objectData.sequenceInfo = (objectData.currentIndex + 1) + _self.settings.labels['sequenceInfo.of'] + objectData.sequenceLength;
244
245			// Add next/prev index
246			objectData.prevIndex = objectData.currentIndex - 1;
247			objectData.nextIndex = objectData.currentIndex + 1;
248
249			return objectData;
250		},
251
252		/**
253		 * Prefixes a data attribute name with defined name from 'settings.attrPrefix'
254		 * to ensure more uniqueness for all lightcase related/used attributes.
255		 *
256		 * @param	{string}	name
257		 * @return	{string}
258		 */
259		_prefixAttributeName: function (name) {
260			return 'data-' + _self.settings.attrPrefix + name;
261		},
262
263		/**
264		 * Determines the link target considering 'settings.href' and data attributes
265		 * but also with a fallback to the default 'href' value.
266		 *
267		 * @return	{string}
268		 */
269		_determineLinkTarget: function () {
270			return _self.settings.href || $(_self.origin).attr(_self._prefixAttributeName('href')) || $(_self.origin).attr('href');
271		},
272
273		/**
274		 * Determines the attribute selector to use, depending on
275		 * whether categorized collections are beeing used or not.
276		 *
277		 * @return	{string}	selector
278		 */
279		_determineAttributeSelector: function () {
280			var	$origin = $(_self.origin),
281				selector = '';
282
283			if (typeof _self.cache.selector !== 'undefined') {
284				selector = _self.cache.selector;
285			} else if (_self.settings.useCategories === true && $origin.attr(_self._prefixAttributeName('categories'))) {
286				var	categories = $origin.attr(_self._prefixAttributeName('categories')).split(' ');
287
288				$.each(categories, function (index, category) {
289					if (index > 0) {
290						selector += ',';
291					}
292					selector += '[' + _self._prefixAttributeName('categories') + '~="' + category + '"]';
293				});
294			} else {
295				selector = '[' + _self.settings.attr + '="' + $origin.attr(_self.settings.attr) + '"]';
296			}
297
298			_self.cache.selector = selector;
299
300			return selector;
301		},
302
303		/**
304		 * Determines the correct resource according to the
305		 * current viewport and density.
306		 *
307		 * @return	{string}	url
308		 */
309		_determineUrl: function () {
310			var	dataUrl = _self._verifyDataUrl(_self._determineLinkTarget()),
311				width = 0,
312				density = 0,
313				supportLevel = '',
314				url;
315
316			$.each(dataUrl, function (index, src) {
317				switch (_self._verifyDataType(src.url)) {
318					case 'video':
319						var	video = document.createElement('video'),
320							videoType = _self._verifyDataType(src.url) + '/' + _self._getFileUrlSuffix(src.url);
321
322						// Check if browser can play this type of video format
323						if (supportLevel !== 'probably' && supportLevel !== video.canPlayType(videoType) && video.canPlayType(videoType) !== '') {
324							supportLevel = video.canPlayType(videoType);
325							url = src.url;
326						}
327						break;
328					default:
329						if (
330							// Check density
331							_self._devicePixelRatio() >= src.density &&
332							src.density >= density &&
333							// Check viewport width
334							_self._matchMedia()('screen and (min-width:' + src.width + 'px)').matches &&
335							src.width >= width
336						) {
337							width = src.width;
338							density = src.density;
339							url = src.url;
340						}
341						break;
342				}
343			});
344
345			return url;
346		},
347
348		/**
349		 * Normalizes an url and returns information about the resource path,
350		 * the viewport width as well as density if defined.
351		 *
352		 * @param	{string}	url	Path to resource in format of an url or srcset
353		 * @return	{object}
354		 */
355		_normalizeUrl: function (url) {
356			var srcExp = /^\d+$/;
357
358            		var urlParser = function (str) {
359                		var src = {
360                    			width: 0,
361                    			density: 0
362                		};
363
364                		str.trim().split(/\s+/).forEach(function (url, i) {
365                   			if (i === 0) {
366                        			return src.url = url;
367                    			}
368
369                    			var value = url.substring(0, url.length - 1),
370                        		lastChar = url[url.length - 1],
371                        		intVal = parseInt(value, 10),
372                        		floatVal = parseFloat(value);
373					if (lastChar === 'w' && srcExp.test(value)) {
374						src.width = intVal;
375					} else if (lastChar === 'h' && srcExp.test(value)) {
376						src.height = intVal;
377					} else if (lastChar === 'x' && !isNaN(floatVal)) {
378						src.density = floatVal;
379					}
380				});
381
382                		return src;
383            		};
384
385			// Data URL detected (no split)
386			if (url.indexOf('data:') === 0) {
387				return [urlParser(url)];
388			}
389
390			// Regular URL, normal behavior
391			return url.split(',').map(urlParser);
392		},
393
394		/**
395		 * Verifies if the link is part of a sequence
396		 *
397		 * @param	{string}	rel
398		 * @param	{string}	expression
399		 * @return	{boolean}
400		 */
401		_isPartOfSequence: function (rel, expression) {
402			var getSimilarLinks = $('[' + _self.settings.attr + '="' + rel + '"]'),
403				regexp = new RegExp(expression);
404
405			return (regexp.test(rel) && getSimilarLinks.length > 1);
406		},
407
408		/**
409		 * Verifies if the slideshow should be enabled
410		 *
411		 * @return	{boolean}
412		 */
413		isSlideshowEnabled: function () {
414			return (_self.objectData.isPartOfSequence && (_self.settings.slideshow === true || _self.objectData.isPartOfSequenceWithSlideshow === true));
415		},
416
417		/**
418		 * Loads the new content to show
419		 *
420		 * @return	{void}
421		 */
422		_loadContent: function () {
423			if (_self.cache.originalObject) {
424				_self._restoreObject();
425			}
426
427			_self._createObject();
428		},
429
430		/**
431		 * Creates a new object
432		 *
433		 * @return	{void}
434		 */
435		_createObject: function () {
436			var $object;
437
438			// Create object
439			switch (_self.objectData.type) {
440				case 'image':
441					$object = $(new Image());
442					$object.attr({
443						// The time expression is required to prevent the binding of an image load
444						'src': _self.objectData.url,
445						'alt': _self.objectData.title
446					});
447					break;
448				case 'inline':
449					$object = $('<div class="' + _self.settings.classPrefix + 'inlineWrap"></div>');
450					$object.html(_self._cloneObject($(_self.objectData.url)));
451
452					// Add custom attributes from _self.settings
453					$.each(_self.settings.inline, function (name, value) {
454						$object.attr(_self._prefixAttributeName(name), value);
455					});
456					break;
457				case 'ajax':
458					$object = $('<div class="' + _self.settings.classPrefix + 'inlineWrap"></div>');
459
460					// Add custom attributes from _self.settings
461					$.each(_self.settings.ajax, function (name, value) {
462						if (name !== 'data') {
463							$object.attr(_self._prefixAttributeName(name), value);
464						}
465					});
466					break;
467				case 'flash':
468					$object = $('<embed src="' + _self.objectData.url + '" type="application/x-shockwave-flash"></embed>');
469
470					// Add custom attributes from _self.settings
471					$.each(_self.settings.flash, function (name, value) {
472						$object.attr(name, value);
473					});
474					break;
475				case 'video':
476					$object = $('<video></video>');
477					$object.attr('src', _self.objectData.url);
478
479					// Add custom attributes from _self.settings
480					$.each(_self.settings.video, function (name, value) {
481						$object.attr(name, value);
482					});
483					break;
484				default:
485					$object = $('<iframe></iframe>');
486					$object.attr({
487						'src': _self.objectData.url
488					});
489
490					// Add custom attributes from _self.settings
491					$.each(_self.settings.iframe, function (name, value) {
492						$object.attr(name, value);
493					});
494					break;
495			}
496
497			_self._addObject($object);
498			_self._loadObject($object);
499		},
500
501		/**
502		 * Adds the new object to the markup
503		 *
504		 * @param	{object}	$object
505		 * @return	{void}
506		 */
507		_addObject: function ($object) {
508			// Add object to content holder
509			_self.objects.contentInner.html($object);
510
511			// Start loading
512			_self._loading('start');
513
514			// Call onStart hook functions
515			_self._callHooks(_self.settings.onStart);
516
517			// Add sequenceInfo to the content holder or hide if its empty
518			if (_self.settings.showSequenceInfo === true && _self.objectData.isPartOfSequence) {
519				_self.objects.sequenceInfo.html(_self.objectData.sequenceInfo);
520				_self.objects.sequenceInfo.show();
521			} else {
522				_self.objects.sequenceInfo.empty();
523				_self.objects.sequenceInfo.hide();
524			}
525			// Add title to the content holder or hide if its empty
526			if (_self.settings.showTitle === true && _self.objectData.title !== undefined && _self.objectData.title !== '') {
527				_self.objects.title.html(_self.objectData.title);
528				_self.objects.title.show();
529			} else {
530				_self.objects.title.empty();
531				_self.objects.title.hide();
532			}
533			// Add caption to the content holder or hide if its empty
534			if (_self.settings.showCaption === true && _self.objectData.caption !== undefined && _self.objectData.caption !== '') {
535				_self.objects.caption.html(_self.objectData.caption);
536				_self.objects.caption.show();
537			} else {
538				_self.objects.caption.empty();
539				_self.objects.caption.hide();
540			}
541		},
542
543		/**
544		 * Loads the new object
545		 *
546		 * @param	{object}	$object
547		 * @return	{void}
548		 */
549		_loadObject: function ($object) {
550			// Load the object
551			switch (_self.objectData.type) {
552				case 'inline':
553					if ($(_self.objectData.url)) {
554						_self._showContent($object);
555					} else {
556						_self.error();
557					}
558					break;
559				case 'ajax':
560					$.ajax(
561						$.extend({}, _self.settings.ajax, {
562							url: _self.objectData.url,
563							type: _self.objectData.requestType,
564							dataType: _self.objectData.requestDataType,
565							data: _self.objectData.requestData,
566							success: function (data, textStatus, jqXHR) {
567								// Check for X-Ajax-Location
568								if (jqXHR.getResponseHeader('X-Ajax-Location')) {
569									_self.objectData.url = jqXHR.getResponseHeader('X-Ajax-Location');
570									_self._loadObject($object);
571								}
572								else {
573									// Unserialize if data is transferred as json
574									if (_self.objectData.requestDataType === 'json') {
575										_self.objectData.data = data;
576									} else {
577										$object.html(data);
578									}
579									_self._showContent($object);
580								}
581							},
582							error: function (jqXHR, textStatus, errorThrown) {
583								_self.error();
584							}
585						})
586					);
587					break;
588				case 'flash':
589					_self._showContent($object);
590					break;
591				case 'video':
592					if (typeof($object.get(0).canPlayType) === 'function' || _self.objects.case.find('video').length === 0) {
593						_self._showContent($object);
594					} else {
595						_self.error();
596					}
597					break;
598				default:
599					if (_self.objectData.url) {
600						$object.on('load', function () {
601							_self._showContent($object);
602						});
603						$object.on('error', function () {
604							_self.error();
605						});
606					} else {
607						_self.error();
608					}
609					break;
610			}
611		},
612
613		/**
614		 * Throws an error message if something went wrong
615		 *
616		 * @return	{void}
617		 */
618		error: function () {
619			_self.objectData.type = 'error';
620			var $object = $('<div class="' + _self.settings.classPrefix + 'inlineWrap"></div>');
621
622			$object.html(_self.settings.errorMessage);
623			_self.objects.contentInner.html($object);
624
625			_self._showContent(_self.objects.contentInner);
626		},
627
628		/**
629		 * Calculates the dimensions to fit content
630		 *
631		 * @param	{object}	$object
632		 * @return	{void}
633		 */
634		_calculateDimensions: function ($object) {
635			_self._cleanupDimensions();
636
637			if (!$object) return;
638
639			// Set default dimensions
640			var dimensions = {
641				ratio: 1,
642				objectWidth: $object.attr('width') ? $object.attr('width') : $object.attr(_self._prefixAttributeName('width')),
643				objectHeight: $object.attr('height') ? $object.attr('height') : $object.attr(_self._prefixAttributeName('height'))
644			};
645
646			if (!_self.settings.disableShrink) {
647				// Add calculated maximum width/height to dimensions
648				dimensions.maxWidth = parseInt(_self.dimensions.windowWidth * _self.settings.shrinkFactor);
649				dimensions.maxHeight = parseInt(_self.dimensions.windowHeight * _self.settings.shrinkFactor);
650
651				// If the auto calculated maxWidth/maxHeight greather than the user-defined one, use that.
652				if (dimensions.maxWidth > _self.settings.maxWidth) {
653					dimensions.maxWidth = _self.settings.maxWidth;
654				}
655				if (dimensions.maxHeight > _self.settings.maxHeight) {
656					dimensions.maxHeight = _self.settings.maxHeight;
657				}
658
659				// Calculate the difference between screen width/height and image width/height
660				dimensions.differenceWidthAsPercent = parseInt(100 / dimensions.maxWidth * dimensions.objectWidth);
661				dimensions.differenceHeightAsPercent = parseInt(100 / dimensions.maxHeight * dimensions.objectHeight);
662
663				switch (_self.objectData.type) {
664					case 'image':
665					case 'flash':
666					case 'video':
667					case 'iframe':
668					case 'ajax':
669					case 'inline':
670						if (_self.objectData.type === 'image' || _self.settings.fixedRatio === true) {
671							if (dimensions.differenceWidthAsPercent > 100 && dimensions.differenceWidthAsPercent > dimensions.differenceHeightAsPercent) {
672								dimensions.objectWidth = dimensions.maxWidth;
673								dimensions.objectHeight = parseInt(dimensions.objectHeight / dimensions.differenceWidthAsPercent * 100);
674							}
675							if (dimensions.differenceHeightAsPercent > 100 && dimensions.differenceHeightAsPercent > dimensions.differenceWidthAsPercent) {
676								dimensions.objectWidth = parseInt(dimensions.objectWidth / dimensions.differenceHeightAsPercent * 100);
677								dimensions.objectHeight = dimensions.maxHeight;
678							}
679							if (dimensions.differenceHeightAsPercent > 100 && dimensions.differenceWidthAsPercent < dimensions.differenceHeightAsPercent) {
680								dimensions.objectWidth = parseInt(dimensions.maxWidth / dimensions.differenceHeightAsPercent * dimensions.differenceWidthAsPercent);
681								dimensions.objectHeight = dimensions.maxHeight;
682							}
683							break;
684						}
685					case 'error':
686						if (!isNaN(dimensions.objectWidth) && dimensions.objectWidth > dimensions.maxWidth) {
687							dimensions.objectWidth = dimensions.maxWidth;
688						}
689						break;
690					default:
691						if ((isNaN(dimensions.objectWidth) || dimensions.objectWidth > dimensions.maxWidth) && !_self.settings.forceWidth) {
692							dimensions.objectWidth = dimensions.maxWidth;
693						}
694						if (((isNaN(dimensions.objectHeight) && dimensions.objectHeight !== 'auto') || dimensions.objectHeight > dimensions.maxHeight) && !_self.settings.forceHeight) {
695							dimensions.objectHeight = dimensions.maxHeight;
696						}
697						break;
698				}
699			}
700
701			if (_self.settings.forceWidth) {
702				try {
703					dimensions.objectWidth = _self.settings[_self.objectData.type].width;
704				} catch (e) {
705					dimensions.objectWidth = _self.settings.width || dimensions.objectWidth;
706				}
707
708				dimensions.maxWidth = null;
709			}
710			if ($object.attr(_self._prefixAttributeName('max-width'))) {
711				dimensions.maxWidth = $object.attr(_self._prefixAttributeName('max-width'));
712			}
713
714			if (_self.settings.forceHeight) {
715				try {
716					dimensions.objectHeight = _self.settings[_self.objectData.type].height;
717				} catch (e) {
718					dimensions.objectHeight = _self.settings.height || dimensions.objectHeight;
719				}
720
721				dimensions.maxHeight = null;
722			}
723			if ($object.attr(_self._prefixAttributeName('max-height'))) {
724				dimensions.maxHeight = $object.attr(_self._prefixAttributeName('max-height'));
725			}
726			_self._adjustDimensions($object, dimensions);
727		},
728
729		/**
730		 * Adjusts the dimensions
731		 *
732		 * @param	{object}	$object
733		 * @param	{object}	dimensions
734		 * @return	{void}
735		 */
736		_adjustDimensions: function ($object, dimensions) {
737			// Adjust width and height
738			$object.css({
739				'width': dimensions.objectWidth,
740				'height': dimensions.objectHeight,
741				'max-width': dimensions.maxWidth,
742				'max-height': dimensions.maxHeight
743			});
744
745			_self.objects.contentInner.css({
746				'width': $object.outerWidth(),
747				'height': $object.outerHeight(),
748				'max-width': '100%'
749			});
750
751			_self.objects.case.css({
752				'width': _self.objects.contentInner.outerWidth(),
753				'max-width': '100%'
754			});
755
756			// Adjust margin
757			_self.objects.case.css({
758				'margin-top': parseInt(-(_self.objects.case.outerHeight() / 2)),
759				'margin-left': parseInt(-(_self.objects.case.outerWidth() / 2))
760			});
761		},
762
763		/**
764		 * Handles the _loading
765		 *
766		 * @param	{string}	process
767		 * @return	{void}
768		 */
769		_loading: function (process) {
770			if (process === 'start') {
771				_self.objects.case.addClass(_self.settings.classPrefix + 'loading');
772				_self.objects.loading.show();
773			} else if (process === 'end') {
774				_self.objects.case.removeClass(_self.settings.classPrefix + 'loading');
775				_self.objects.loading.hide();
776			}
777		},
778
779
780		/**
781		 * Gets the client screen dimensions
782		 *
783		 * @return	{object}	dimensions
784		 */
785		getViewportDimensions: function () {
786			return {
787				windowWidth: $(window).innerWidth(),
788				windowHeight: $(window).innerHeight()
789			};
790		},
791
792		/**
793		 * Verifies the url
794		 *
795		 * @param	{string}	dataUrl
796		 * @return	{object}	dataUrl	Clean url for processing content
797		 */
798		_verifyDataUrl: function (dataUrl) {
799			if (!dataUrl || dataUrl === undefined || dataUrl === '') {
800				return false;
801			}
802
803			if (dataUrl.indexOf('#') > -1) {
804				dataUrl = dataUrl.split('#');
805				dataUrl = '#' + dataUrl[dataUrl.length - 1];
806			}
807
808			return _self._normalizeUrl(dataUrl.toString());
809		},
810
811			//
812		/**
813		 * Tries to get the (file) suffix of an url
814		 *
815		 * @param	{string}	url
816		 * @return	{string}
817		 */
818		_getFileUrlSuffix: function (url) {
819			var re = /(?:\.([^.]+))?$/;
820			return re.exec(url.toLowerCase())[1];
821		},
822
823		/**
824		 * Verifies the data type of the content to load
825		 *
826		 * @param	{string}			url
827		 * @return	{string|boolean}	Array key if expression matched, else false
828		 */
829		_verifyDataType: function (url) {
830			var typeMapping = _self.settings.typeMapping;
831
832			// Early abort if dataUrl couldn't be verified
833			if (!url) {
834				return false;
835			}
836			
837			//checking if user defined type is valid
838			if (_self.settings.type) {
839				for (var key in typeMapping) {
840					if (key === _self.settings.type) {
841						return _self.settings.type;
842					}
843				}
844			}
845
846			// Verify the dataType of url according to typeMapping which
847			// has been defined in settings.
848			for (var key in typeMapping) {
849				if (typeMapping.hasOwnProperty(key)) {
850					var suffixArr = typeMapping[key].split(',');
851
852					for (var i = 0; i < suffixArr.length; i++) {
853						var suffix = suffixArr[i].toLowerCase(),
854							regexp = new RegExp('\.(' + suffix + ')$', 'i'),
855							str = url.toLowerCase().split('?')[0].substr(-5);
856
857						if (regexp.test(str) === true || (key === 'inline' && (url.indexOf(suffix) > -1))) {
858							return key;
859						}
860					}
861				}
862			}
863
864			// If no expression matched, return 'iframe'.
865			return 'iframe';
866		},
867
868		/**
869		 * Extends html markup with the essential tags
870		 *
871		 * @return	{void}
872		 */
873		_addElements: function () {
874			if (typeof _self.objects.case !== 'undefined' && $('#' + _self.objects.case.attr('id')).length) {
875				return;
876			}
877
878			_self.settings.markup();
879		},
880
881		/**
882		 * Shows the loaded content
883		 *
884		 * @param	{object}	$object
885		 * @return	{void}
886		 */
887		_showContent: function ($object) {
888			// Add data attribute with the object type
889			_self.objects.document.attr(_self._prefixAttributeName('type'), _self.objectData.type);
890
891			_self.cache.object = $object;
892
893			// Call onBeforeShow hook functions
894			_self._callHooks(_self.settings.onBeforeShow);
895
896			if (_self.settings.breakBeforeShow) return;
897			_self.show();
898		},
899
900		/**
901		 * Starts the 'inTransition'
902		 * @return	{void}
903		 */
904		_startInTransition: function () {
905			switch (_self.transition.in()) {
906				case 'scrollTop':
907				case 'scrollRight':
908				case 'scrollBottom':
909				case 'scrollLeft':
910				case 'scrollHorizontal':
911				case 'scrollVertical':
912					_self.transition.scroll(_self.objects.case, 'in', _self.settings.speedIn);
913					_self.transition.fade(_self.objects.contentInner, 'in', _self.settings.speedIn);
914					break;
915				case 'elastic':
916					if (_self.objects.case.css('opacity') < 1) {
917						_self.transition.zoom(_self.objects.case, 'in', _self.settings.speedIn);
918						_self.transition.fade(_self.objects.contentInner, 'in', _self.settings.speedIn);
919				}
920				case 'fade':
921				case 'fadeInline':
922					_self.transition.fade(_self.objects.case, 'in', _self.settings.speedIn);
923					_self.transition.fade(_self.objects.contentInner, 'in', _self.settings.speedIn);
924					break;
925				default:
926					_self.transition.fade(_self.objects.case, 'in', 0);
927					break;
928			}
929
930			// End loading.
931			_self._loading('end');
932			_self.isBusy = false;
933
934			// Set index of the first item opened
935			if (!_self.cache.firstOpened) {
936				_self.cache.firstOpened = _self.objectData.this;
937			}
938
939			// Fade in the info with delay
940			_self.objects.info.hide();
941			setTimeout(function () {
942				 _self.transition.fade(_self.objects.info, 'in', _self.settings.speedIn);
943			}, _self.settings.speedIn);
944
945			// Call onFinish hook functions
946			_self._callHooks(_self.settings.onFinish);
947		},
948
949		/**
950		 * Processes the content to show
951		 *
952		 * @return	{void}
953		 */
954		_processContent: function () {
955			_self.isBusy = true;
956
957			// Fade out the info at first
958			_self.transition.fade(_self.objects.info, 'out', 0);
959
960			switch (_self.settings.transitionOut) {
961				case 'scrollTop':
962				case 'scrollRight':
963				case 'scrollBottom':
964				case 'scrollLeft':
965				case 'scrollVertical':
966				case 'scrollHorizontal':
967					if (_self.objects.case.is(':hidden')) {
968						_self.transition.fade(_self.objects.contentInner, 'out', 0);
969						_self.transition.fade(_self.objects.case, 'out', 0, 0, function () {
970							_self._loadContent();
971						});
972					} else {
973						_self.transition.scroll(_self.objects.case, 'out', _self.settings.speedOut, function () {
974							_self._loadContent();
975						});
976					}
977					break;
978				case 'fade':
979					if (_self.objects.case.is(':hidden')) {
980						_self.transition.fade(_self.objects.case, 'out', 0, 0, function () {
981							_self._loadContent();
982						});
983					} else {
984						_self.transition.fade(_self.objects.case, 'out', _self.settings.speedOut, 0, function () {
985							_self._loadContent();
986						});
987					}
988					break;
989				case 'fadeInline':
990				case 'elastic':
991					if (_self.objects.case.is(':hidden')) {
992						_self.transition.fade(_self.objects.case, 'out', 0, 0, function () {
993							_self._loadContent();
994						});
995					} else {
996						_self.transition.fade(_self.objects.contentInner, 'out', _self.settings.speedOut, 0, function () {
997							_self._loadContent();
998						});
999					}
1000					break;
1001				default:
1002					_self.transition.fade(_self.objects.case, 'out', 0, 0, function () {
1003						_self._loadContent();
1004					});
1005					break;
1006			}
1007		},
1008
1009		/**
1010		 * Handles events for gallery buttons
1011		 *
1012		 * @return	{void}
1013		 */
1014		_handleEvents: function () {
1015			_self._unbindEvents();
1016
1017			_self.objects.nav.children().not(_self.objects.close).hide();
1018
1019			// If slideshow is enabled, show play/pause and start timeout.
1020			if (_self.isSlideshowEnabled()) {
1021				// Only start the timeout if slideshow autostart is enabled and slideshow is not pausing
1022				if (
1023					(_self.settings.slideshowAutoStart === true || _self.isSlideshowStarted) &&
1024					!_self.objects.nav.hasClass(_self.settings.classPrefix + 'paused')
1025				) {
1026					_self._startTimeout();
1027				} else {
1028					_self._stopTimeout();
1029				}
1030			}
1031
1032			if (_self.settings.liveResize) {
1033				_self._watchResizeInteraction();
1034			}
1035
1036			_self.objects.close.click(function (event) {
1037				event.preventDefault();
1038				_self.close();
1039			});
1040
1041			if (_self.settings.closeOnOverlayClick === true) {
1042				_self.objects.overlay.css('cursor', 'pointer').click(function (event) {
1043					event.preventDefault();
1044
1045					_self.close();
1046				});
1047			}
1048
1049			if (_self.settings.useKeys === true) {
1050				_self._addKeyEvents();
1051			}
1052
1053			if (_self.objectData.isPartOfSequence) {
1054				_self.objects.nav.attr(_self._prefixAttributeName('ispartofsequence'), true);
1055				_self.objects.nav.data('items', _self._setNavigation());
1056
1057				_self.objects.prev.click(function (event) {
1058					event.preventDefault();
1059
1060					if (_self.settings.navigateEndless === true || !_self.item.isFirst()) {
1061						_self.objects.prev.unbind('click');
1062						_self.cache.action = 'prev';
1063						_self.objects.nav.data('items').prev.click();
1064
1065						if (_self.isSlideshowEnabled()) {
1066							_self._stopTimeout();
1067						}
1068					}
1069				});
1070
1071				_self.objects.next.click(function (event) {
1072					event.preventDefault();
1073
1074					if (_self.settings.navigateEndless === true || !_self.item.isLast()) {
1075						_self.objects.next.unbind('click');
1076						_self.cache.action = 'next';
1077						_self.objects.nav.data('items').next.click();
1078
1079						if (_self.isSlideshowEnabled()) {
1080							_self._stopTimeout();
1081						}
1082					}
1083				});
1084
1085				if (_self.isSlideshowEnabled()) {
1086					_self.objects.play.click(function (event) {
1087						event.preventDefault();
1088						_self._startTimeout();
1089					});
1090					_self.objects.pause.click(function (event) {
1091						event.preventDefault();
1092						_self._stopTimeout();
1093					});
1094				}
1095
1096				// Enable swiping if activated
1097				if (_self.settings.swipe === true) {
1098					if ($.isPlainObject($.event.special.swipeleft)) {
1099						_self.objects.case.on('swipeleft', function (event) {
1100							event.preventDefault();
1101							_self.objects.next.click();
1102							if (_self.isSlideshowEnabled()) {
1103								_self._stopTimeout();
1104							}
1105						});
1106					}
1107					if ($.isPlainObject($.event.special.swiperight)) {
1108						_self.objects.case.on('swiperight', function (event) {
1109							event.preventDefault();
1110							_self.objects.prev.click();
1111							if (_self.isSlideshowEnabled()) {
1112								_self._stopTimeout();
1113							}
1114						});
1115					}
1116				}
1117			}
1118		},
1119
1120		/**
1121		 * Adds the key events
1122		 *
1123		 * @return	{void}
1124		 */
1125		_addKeyEvents: function () {
1126			$(document).bind('keyup.lightcase', function (event) {
1127				// Do nothing if lightcase is in process
1128				if (_self.isBusy) {
1129					return;
1130				}
1131
1132				switch (event.keyCode) {
1133					// Escape key
1134					case 27:
1135						_self.objects.close.click();
1136						break;
1137					// Backward key
1138					case 37:
1139						if (_self.objectData.isPartOfSequence) {
1140							_self.objects.prev.click();
1141						}
1142						break;
1143					// Forward key
1144					case 39:
1145						if (_self.objectData.isPartOfSequence) {
1146							_self.objects.next.click();
1147						}
1148						break;
1149				}
1150			});
1151		},
1152
1153		/**
1154		 * Starts the slideshow timeout
1155		 *
1156		 * @return	{void}
1157		 */
1158		_startTimeout: function () {
1159			_self.isSlideshowStarted = true;
1160
1161			_self.objects.play.hide();
1162			_self.objects.pause.show();
1163
1164			_self.cache.action = 'next';
1165			_self.objects.nav.removeClass(_self.settings.classPrefix + 'paused');
1166
1167			_self.timeout = setTimeout(function () {
1168				_self.objects.nav.data('items').next.click();
1169			}, _self.settings.timeout);
1170		},
1171
1172		/**
1173		 * Stops the slideshow timeout
1174		 *
1175		 * @return	{void}
1176		 */
1177		_stopTimeout: function () {
1178			_self.objects.play.show();
1179			_self.objects.pause.hide();
1180
1181			_self.objects.nav.addClass(_self.settings.classPrefix + 'paused');
1182
1183			clearTimeout(_self.timeout);
1184		},
1185
1186		/**
1187		 * Sets the navigator buttons (prev/next)
1188		 *
1189		 * @return	{object}	items
1190		 */
1191		_setNavigation: function () {
1192			var $links = $((_self.cache.selector || _self.settings.attr)),
1193				sequenceLength = _self.objectData.sequenceLength - 1,
1194				items = {
1195					prev: $links.eq(_self.objectData.prevIndex),
1196					next: $links.eq(_self.objectData.nextIndex)
1197				};
1198
1199			if (_self.objectData.currentIndex > 0) {
1200				_self.objects.prev.show();
1201			} else {
1202				items.prevItem = $links.eq(sequenceLength);
1203			}
1204			if (_self.objectData.nextIndex <= sequenceLength) {
1205				_self.objects.next.show();
1206			} else {
1207				items.next = $links.eq(0);
1208			}
1209
1210			if (_self.settings.navigateEndless === true) {
1211				_self.objects.prev.show();
1212				_self.objects.next.show();
1213			}
1214
1215			return items;
1216		},
1217
1218		/**
1219		 * Item information/status
1220		 *
1221		 */
1222		item: {
1223			/**
1224			 * Verifies if the current item is first item.
1225			 *
1226			 * @return	{boolean}
1227			 */
1228			isFirst: function () {
1229				return (_self.objectData.currentIndex === 0);
1230			},
1231
1232			/**
1233			 * Verifies if the current item is first item opened.
1234			 *
1235			 * @return	{boolean}
1236			 */
1237			isFirstOpened: function () {
1238				return _self.objectData.this.is(_self.cache.firstOpened);
1239			},
1240
1241			/**
1242			 * Verifies if the current item is last item.
1243			 *
1244			 * @return	{boolean}
1245			 */
1246			isLast: function () {
1247				return (_self.objectData.currentIndex === (_self.objectData.sequenceLength - 1));
1248			}
1249		},
1250
1251		/**
1252		 * Clones the object for inline elements
1253		 *
1254		 * @param	{object}	$object
1255		 * @return	{object}	$clone
1256		 */
1257		_cloneObject: function ($object) {
1258			var $clone = $object.clone(),
1259				objectId = $object.attr('id');
1260
1261			// If element is hidden, cache the object and remove
1262			if ($object.is(':hidden')) {
1263				_self._cacheObjectData($object);
1264				$object.attr('id', _self.settings.idPrefix + 'temp-' + objectId).empty();
1265			} else {
1266				// Prevent duplicated id's
1267				$clone.removeAttr('id');
1268			}
1269
1270			return $clone.show();
1271		},
1272
1273		/**
1274		 * Verifies if it is a mobile device
1275		 *
1276		 * @return	{boolean}
1277		 */
1278		isMobileDevice: function () {
1279			var deviceAgent = navigator.userAgent.toLowerCase(),
1280				agentId = deviceAgent.match(_self.settings.mobileMatchExpression);
1281
1282			return agentId ? true : false;
1283		},
1284
1285		/**
1286		 * Verifies if css transitions are supported
1287		 *
1288		 * @return	{string|boolean}	The transition prefix if supported, else false.
1289		 */
1290		isTransitionSupported: function () {
1291			var body = _self.objects.body.get(0),
1292				isTransitionSupported = false,
1293				transitionMapping = {
1294					'transition': '',
1295					'WebkitTransition': '-webkit-',
1296					'MozTransition': '-moz-',
1297					'OTransition': '-o-',
1298					'MsTransition': '-ms-'
1299				};
1300
1301			for (var key in transitionMapping) {
1302				if (transitionMapping.hasOwnProperty(key) && key in body.style) {
1303					_self.support.transition = transitionMapping[key];
1304					isTransitionSupported = true;
1305				}
1306			}
1307
1308			return isTransitionSupported;
1309		},
1310
1311		/**
1312		 * Transition types
1313		 *
1314		 */
1315		transition: {
1316			/**
1317			 * Returns the correct transition type according to the status of interaction.
1318			 *
1319			 * @return	{string}	Transition type
1320			 */
1321			in: function () {
1322				if (_self.settings.transitionOpen && !_self.cache.firstOpened) {
1323					return _self.settings.transitionOpen;
1324				}
1325				return _self.settings.transitionIn;
1326			},
1327
1328			/**
1329			 * Fades in/out the object
1330			 *
1331			 * @param	{object}	$object
1332			 * @param	{string}	type
1333			 * @param	{number}	speed
1334			 * @param	{number}	opacity
1335			 * @param	{function}	callback
1336			 * @return	{void}		Animates an object
1337			 */
1338			fade: function ($object, type, speed, opacity, callback) {
1339				var isInTransition = type === 'in',
1340					startTransition = {},
1341					startOpacity = $object.css('opacity'),
1342					endTransition = {},
1343					endOpacity = opacity ? opacity: isInTransition ? 1 : 0;
1344
1345				if (!_self.isOpen && isInTransition) return;
1346
1347				startTransition['opacity'] = startOpacity;
1348				endTransition['opacity'] = endOpacity;
1349
1350				$object.css(_self.support.transition + 'transition', 'none');
1351				$object.css(startTransition).show();
1352
1353				// Css transition
1354				if (_self.support.transitions) {
1355					endTransition[_self.support.transition + 'transition'] = speed + 'ms ease';
1356
1357					setTimeout(function () {
1358						$object.css(endTransition);
1359
1360						setTimeout(function () {
1361							$object.css(_self.support.transition + 'transition', '');
1362
1363							if (callback && (_self.isOpen || !isInTransition)) {
1364								callback();
1365							}
1366						}, speed);
1367					}, 15);
1368				} else {
1369					// Fallback to js transition
1370					$object.stop();
1371					$object.animate(endTransition, speed, callback);
1372				}
1373			},
1374
1375			/**
1376			 * Scrolls in/out the object
1377			 *
1378			 * @param	{object}	$object
1379			 * @param	{string}	type
1380			 * @param	{number}	speed
1381			 * @param	{function}	callback
1382			 * @return	{void}		Animates an object
1383			 */
1384			scroll: function ($object, type, speed, callback) {
1385				var isInTransition = type === 'in',
1386					transition = isInTransition ? _self.settings.transitionIn : _self.settings.transitionOut,
1387					direction = 'left',
1388					startTransition = {},
1389					startOpacity = isInTransition ? 0 : 1,
1390					startOffset = isInTransition ? '-50%' : '50%',
1391					endTransition = {},
1392					endOpacity = isInTransition ? 1 : 0,
1393					endOffset = isInTransition ? '50%' : '-50%';
1394
1395				if (!_self.isOpen && isInTransition) return;
1396
1397				switch (transition) {
1398					case 'scrollTop':
1399						direction = 'top';
1400						break;
1401					case 'scrollRight':
1402						startOffset = isInTransition ? '150%' : '50%';
1403						endOffset = isInTransition ? '50%' : '150%';
1404						break;
1405					case 'scrollBottom':
1406						direction = 'top';
1407						startOffset = isInTransition ? '150%' : '50%';
1408						endOffset = isInTransition ? '50%' : '150%';
1409						break;
1410					case 'scrollHorizontal':
1411						startOffset = isInTransition ? '150%' : '50%';
1412						endOffset = isInTransition ? '50%' : '-50%';
1413						break;
1414					case 'scrollVertical':
1415						direction = 'top';
1416						startOffset = isInTransition ? '-50%' : '50%';
1417						endOffset = isInTransition ? '50%' : '150%';
1418						break;
1419				}
1420
1421				if (_self.cache.action === 'prev') {
1422					switch (transition) {
1423						case 'scrollHorizontal':
1424							startOffset = isInTransition ? '-50%' : '50%';
1425							endOffset = isInTransition ? '50%' : '150%';
1426							break;
1427						case 'scrollVertical':
1428							startOffset = isInTransition ? '150%' : '50%';
1429							endOffset = isInTransition ? '50%' : '-50%';
1430							break;
1431					}
1432				}
1433
1434				startTransition['opacity'] = startOpacity;
1435				startTransition[direction] = startOffset;
1436
1437				endTransition['opacity'] = endOpacity;
1438				endTransition[direction] = endOffset;
1439
1440				$object.css(_self.support.transition + 'transition', 'none');
1441				$object.css(startTransition).show();
1442
1443				// Css transition
1444				if (_self.support.transitions) {
1445					endTransition[_self.support.transition + 'transition'] = speed + 'ms ease';
1446
1447					setTimeout(function () {
1448						$object.css(endTransition);
1449
1450						setTimeout(function () {
1451							$object.css(_self.support.transition + 'transition', '');
1452
1453							if (callback && (_self.isOpen || !isInTransition)) {
1454								callback();
1455							}
1456						}, speed);
1457					}, 15);
1458				} else {
1459					// Fallback to js transition
1460					$object.stop();
1461					$object.animate(endTransition, speed, callback);
1462				}
1463			},
1464
1465			/**
1466			 * Zooms in/out the object
1467			 *
1468			 * @param	{object}	$object
1469			 * @param	{string}	type
1470			 * @param	{number}	speed
1471			 * @param	{function}	callback
1472			 * @return	{void}		Animates an object
1473			 */
1474			zoom: function ($object, type, speed, callback) {
1475				var isInTransition = type === 'in',
1476					startTransition = {},
1477					startOpacity = $object.css('opacity'),
1478					startScale = isInTransition ? 'scale(0.75)' : 'scale(1)',
1479					endTransition = {},
1480					endOpacity = isInTransition ? 1 : 0,
1481					endScale = isInTransition ? 'scale(1)' : 'scale(0.75)';
1482
1483				if (!_self.isOpen && isInTransition) return;
1484
1485				startTransition['opacity'] = startOpacity;
1486				startTransition[_self.support.transition + 'transform'] = startScale;
1487
1488				endTransition['opacity'] = endOpacity;
1489
1490				$object.css(_self.support.transition + 'transition', 'none');
1491				$object.css(startTransition).show();
1492
1493				// Css transition
1494				if (_self.support.transitions) {
1495					endTransition[_self.support.transition + 'transform'] = endScale;
1496					endTransition[_self.support.transition + 'transition'] = speed + 'ms ease';
1497
1498					setTimeout(function () {
1499						$object.css(endTransition);
1500
1501						setTimeout(function () {
1502							$object.css(_self.support.transition + 'transform', '');
1503							$object.css(_self.support.transition + 'transition', '');
1504
1505							if (callback && (_self.isOpen || !isInTransition)) {
1506								callback();
1507							}
1508						}, speed);
1509					}, 15);
1510				} else {
1511					// Fallback to js transition
1512					$object.stop();
1513					$object.animate(endTransition, speed, callback);
1514				}
1515			}
1516		},
1517
1518		/**
1519		 * Calls all the registered functions of a specific hook
1520		 *
1521		 * @param	{object}	hooks
1522		 * @return	{void}
1523		 */
1524		_callHooks: function (hooks) {
1525			if (typeof(hooks) === 'object') {
1526				$.each(hooks, function(index, hook) {
1527					if (typeof(hook) === 'function') {
1528						hook.call(_self.origin);
1529					}
1530				});
1531			}
1532		},
1533
1534		/**
1535		 * Caches the object data
1536		 *
1537		 * @param	{object}	$object
1538		 * @return	{void}
1539		 */
1540		_cacheObjectData: function ($object) {
1541			$.data($object, 'cache', {
1542				id: $object.attr('id'),
1543				content: $object.html()
1544			});
1545
1546			_self.cache.originalObject = $object;
1547		},
1548
1549		/**
1550		 * Restores the object from cache
1551		 *
1552		 * @return	void
1553		 */
1554		_restoreObject: function () {
1555			var $object = $('[id^="' + _self.settings.idPrefix + 'temp-"]');
1556
1557			$object.attr('id', $.data(_self.cache.originalObject, 'cache').id);
1558			$object.html($.data(_self.cache.originalObject, 'cache').content);
1559		},
1560
1561		/**
1562		 * Executes functions for a window resize.
1563		 * It stops an eventual timeout and recalculates dimensions.
1564		 *
1565		 * @param	{object}	dimensions
1566		 * @return	{void}
1567		 */
1568		resize: function (event, dimensions) {
1569			if (!_self.isOpen) return;
1570
1571			if (_self.isSlideshowEnabled()) {
1572				_self._stopTimeout();
1573			}
1574
1575			if (typeof dimensions === 'object' && dimensions !== null) {
1576				if (dimensions.width) {
1577					_self.cache.object.attr(
1578						_self._prefixAttributeName('width'),
1579						dimensions.width
1580					);
1581				}
1582				if (dimensions.maxWidth) {
1583					_self.cache.object.attr(
1584						_self._prefixAttributeName('max-width'),
1585						dimensions.maxWidth
1586					);
1587				}
1588				if (dimensions.height) {
1589					_self.cache.object.attr(
1590						_self._prefixAttributeName('height'),
1591						dimensions.height
1592					);
1593				}
1594				if (dimensions.maxHeight) {
1595					_self.cache.object.attr(
1596						_self._prefixAttributeName('max-height'),
1597						dimensions.maxHeight
1598					);
1599				}
1600			}
1601
1602			_self.dimensions = _self.getViewportDimensions();
1603			_self._calculateDimensions(_self.cache.object);
1604
1605			// Call onResize hook functions
1606			_self._callHooks(_self.settings.onResize);
1607		},
1608
1609		/**
1610		 * Watches for any resize interaction and caches the new sizes.
1611		 *
1612		 * @return	{void}
1613		 */
1614		_watchResizeInteraction: function () {
1615			$(window).resize(_self.resize);
1616		},
1617
1618		/**
1619		 * Stop watching any resize interaction related to _self.
1620		 *
1621		 * @return	{void}
1622		 */
1623		_unwatchResizeInteraction: function () {
1624			$(window).off('resize', _self.resize);
1625		},
1626
1627		/**
1628		 * Switches to the fullscreen mode
1629		 *
1630		 * @return	{void}
1631		 */
1632		_switchToFullScreenMode: function () {
1633			_self.settings.shrinkFactor = 1;
1634			_self.settings.overlayOpacity = 1;
1635
1636			$('html').addClass(_self.settings.classPrefix + 'fullScreenMode');
1637		},
1638
1639		/**
1640		 * Enters into the lightcase view
1641		 *
1642		 * @return	{void}
1643		 */
1644		_open: function () {
1645			_self.isOpen = true;
1646
1647			_self.support.transitions = _self.settings.cssTransitions ? _self.isTransitionSupported() : false;
1648			_self.support.mobileDevice = _self.isMobileDevice();
1649
1650			if (_self.support.mobileDevice) {
1651				$('html').addClass(_self.settings.classPrefix + 'isMobileDevice');
1652
1653				if (_self.settings.fullScreenModeForMobile) {
1654					_self._switchToFullScreenMode();
1655				}
1656			}
1657
1658			if (!_self.settings.transitionIn) {
1659				_self.settings.transitionIn = _self.settings.transition;
1660			}
1661			if (!_self.settings.transitionOut) {
1662				_self.settings.transitionOut = _self.settings.transition;
1663			}
1664
1665			switch (_self.transition.in()) {
1666				case 'fade':
1667				case 'fadeInline':
1668				case 'elastic':
1669				case 'scrollTop':
1670				case 'scrollRight':
1671				case 'scrollBottom':
1672				case 'scrollLeft':
1673				case 'scrollVertical':
1674				case 'scrollHorizontal':
1675					if (_self.objects.case.is(':hidden')) {
1676						_self.objects.close.css('opacity', 0);
1677						_self.objects.overlay.css('opacity', 0);
1678						_self.objects.case.css('opacity', 0);
1679						_self.objects.contentInner.css('opacity', 0);
1680					}
1681					_self.transition.fade(_self.objects.overlay, 'in', _self.settings.speedIn, _self.settings.overlayOpacity, function () {
1682						_self.transition.fade(_self.objects.close, 'in', _self.settings.speedIn);
1683						_self._handleEvents();
1684						_self._processContent();
1685					});
1686					break;
1687				default:
1688					_self.transition.fade(_self.objects.overlay, 'in', 0, _self.settings.overlayOpacity, function () {
1689						_self.transition.fade(_self.objects.close, 'in', 0);
1690						_self._handleEvents();
1691						_self._processContent();
1692					});
1693					break;
1694			}
1695
1696			_self.objects.document.addClass(_self.settings.classPrefix + 'open');
1697			_self.objects.case.attr('aria-hidden', 'false');
1698		},
1699
1700		/**
1701		 * Shows the lightcase by starting the transition
1702		 */
1703		show: function () {
1704			// Call onCalculateDimensions hook functions
1705			_self._callHooks(_self.settings.onBeforeCalculateDimensions);
1706
1707			_self._calculateDimensions(_self.cache.object);
1708
1709			// Call onAfterCalculateDimensions hook functions
1710			_self._callHooks(_self.settings.onAfterCalculateDimensions);
1711
1712			_self._startInTransition();
1713		},
1714
1715		/**
1716		 * Escapes from the lightcase view
1717		 *
1718		 * @return	{void}
1719		 */
1720		close: function () {
1721			_self.isOpen = false;
1722
1723			if (_self.isSlideshowEnabled()) {
1724				_self._stopTimeout();
1725				_self.isSlideshowStarted = false;
1726				_self.objects.nav.removeClass(_self.settings.classPrefix + 'paused');
1727			}
1728
1729			_self.objects.loading.hide();
1730
1731			_self._unbindEvents();
1732
1733			_self._unwatchResizeInteraction();
1734
1735			$('html').removeClass(_self.settings.classPrefix + 'open');
1736			_self.objects.case.attr('aria-hidden', 'true');
1737
1738			_self.objects.nav.children().hide();
1739			_self.objects.close.hide();
1740
1741			// Call onClose hook functions
1742			_self._callHooks(_self.settings.onClose);
1743
1744			// Fade out the info at first
1745			_self.transition.fade(_self.objects.info, 'out', 0);
1746
1747			switch (_self.settings.transitionClose || _self.settings.transitionOut) {
1748				case 'fade':
1749				case 'fadeInline':
1750				case 'scrollTop':
1751				case 'scrollRight':
1752				case 'scrollBottom':
1753				case 'scrollLeft':
1754				case 'scrollHorizontal':
1755				case 'scrollVertical':
1756					_self.transition.fade(_self.objects.case, 'out', _self.settings.speedOut, 0, function () {
1757						_self.transition.fade(_self.objects.overlay, 'out', _self.settings.speedOut, 0, function () {
1758							_self.cleanup();
1759						});
1760					});
1761					break;
1762				case 'elastic':
1763					_self.transition.zoom(_self.objects.case, 'out', _self.settings.speedOut, function () {
1764						_self.transition.fade(_self.objects.overlay, 'out', _self.settings.speedOut, 0, function () {
1765							_self.cleanup();
1766						});
1767					});
1768					break;
1769				default:
1770					_self.cleanup();
1771					break;
1772			}
1773		},
1774
1775		/**
1776		 * Unbinds all given events
1777		 *
1778		 * @return	{void}
1779		 */
1780		_unbindEvents: function () {
1781			// Unbind overlay event
1782			_self.objects.overlay.unbind('click');
1783
1784			// Unbind key events
1785			$(document).unbind('keyup.lightcase');
1786
1787			// Unbind swipe events
1788			_self.objects.case.unbind('swipeleft').unbind('swiperight');
1789
1790			// Unbind navigator events
1791			_self.objects.prev.unbind('click');
1792			_self.objects.next.unbind('click');
1793			_self.objects.play.unbind('click');
1794			_self.objects.pause.unbind('click');
1795
1796			// Unbind close event
1797			_self.objects.close.unbind('click');
1798		},
1799
1800		/**
1801		 * Cleans up the dimensions
1802		 *
1803		 * @return	{void}
1804		 */
1805		_cleanupDimensions: function () {
1806			var opacity = _self.objects.contentInner.css('opacity');
1807
1808			_self.objects.case.css({
1809				'width': '',
1810				'height': '',
1811				'top': '',
1812				'left': '',
1813				'margin-top': '',
1814				'margin-left': ''
1815			});
1816
1817			_self.objects.contentInner.removeAttr('style').css('opacity', opacity);
1818			_self.objects.contentInner.children().removeAttr('style');
1819		},
1820
1821		/**
1822		 * Cleanup after aborting lightcase
1823		 *
1824		 * @return	{void}
1825		 */
1826		cleanup: function () {
1827			_self._cleanupDimensions();
1828
1829			_self.objects.loading.hide();
1830			_self.objects.overlay.hide();
1831			_self.objects.case.hide();
1832			_self.objects.prev.hide();
1833			_self.objects.next.hide();
1834			_self.objects.play.hide();
1835			_self.objects.pause.hide();
1836
1837			_self.objects.document.removeAttr(_self._prefixAttributeName('type'));
1838			_self.objects.nav.removeAttr(_self._prefixAttributeName('ispartofsequence'));
1839
1840			_self.objects.contentInner.empty().hide();
1841			_self.objects.info.children().empty();
1842
1843			if (_self.cache.originalObject) {
1844				_self._restoreObject();
1845			}
1846
1847			// Call onCleanup hook functions
1848			_self._callHooks(_self.settings.onCleanup);
1849
1850			// Restore cache
1851			_self.cache = {};
1852		},
1853
1854		/**
1855		 * Returns the supported match media or undefined if the browser
1856		 * doesn't support match media.
1857		 *
1858		 * @return	{mixed}
1859		 */
1860		_matchMedia: function () {
1861			return window.matchMedia || window.msMatchMedia;
1862		},
1863
1864		/**
1865		 * Returns the devicePixelRatio if supported. Else, it simply returns
1866		 * 1 as the default.
1867		 *
1868		 * @return	{number}
1869		 */
1870		_devicePixelRatio: function () {
1871			return window.devicePixelRatio || 1;
1872		},
1873
1874		/**
1875		 * Checks if method is public
1876		 *
1877		 * @return	{boolean}
1878		 */
1879		_isPublicMethod: function (method) {
1880			return (typeof _self[method] === 'function' && method.charAt(0) !== '_');
1881		},
1882
1883		/**
1884		 * Exports all public methods to be accessible, callable
1885		 * from global scope.
1886		 *
1887		 * @return	{void}
1888		 */
1889		_export: function () {
1890			window.lightcase = {};
1891
1892			$.each(_self, function (property) {
1893				if (_self._isPublicMethod(property)) {
1894					lightcase[property] = _self[property];
1895				}
1896			});
1897		}
1898	};
1899
1900	_self._export();
1901
1902	$.fn.lightcase = function (method) {
1903		// Method calling logic (only public methods are applied)
1904		if (_self._isPublicMethod(method)) {
1905			return _self[method].apply(this, Array.prototype.slice.call(arguments, 1));
1906		} else if (typeof method === 'object' || !method) {
1907			return _self.init.apply(this, arguments);
1908		} else {
1909			$.error('Method ' + method + ' does not exist on jQuery.lightcase');
1910		}
1911	};
1912})(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.