PluginProbe
Photonic Gallery & Lightbox for Flickr, SmugMug & Others / 2.25
Photonic Gallery & Lightbox for Flickr, SmugMug & Others v2.25
3.36 3.35 3.34 3.33 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 2.30 2.31 2.32 2.33 2.34 2.40 2.41 2.42 2.43 2.44 All 141 releases
photonic / include / scripts / third-party / lightcase / lightcase.js

lightcase.js in Photonic Gallery & Lightbox for Flickr, SmugMug & Others 2.25, at include/scripts/third-party/lightcase/lightcase.js

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