1893 lines
51 KiB
JavaScript
1893 lines
51 KiB
JavaScript
/*
|
|
* Lightcase - jQuery Plugin
|
|
* The smart and flexible Lightbox Plugin.
|
|
*
|
|
* @author Cornel Boppart <cornel@bopp-art.com>
|
|
* @copyright Author
|
|
*
|
|
* @version 2.5.0 (11/03/2018)
|
|
*/
|
|
|
|
;(function ($) {
|
|
|
|
'use strict';
|
|
|
|
var _self = {
|
|
cache: {},
|
|
|
|
support: {},
|
|
|
|
objects: {},
|
|
|
|
/**
|
|
* Initializes the plugin
|
|
*
|
|
* @param {object} options
|
|
* @return {object}
|
|
*/
|
|
init: function (options) {
|
|
return this.each(function () {
|
|
$(this).unbind('click.lightcase').bind('click.lightcase', function (event) {
|
|
event.preventDefault();
|
|
$(this).lightcase('start', options);
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Starts the plugin
|
|
*
|
|
* @param {object} options
|
|
* @return {void}
|
|
*/
|
|
start: function (options) {
|
|
_self.origin = lightcase.origin = this;
|
|
|
|
_self.settings = lightcase.settings = $.extend(true, {
|
|
idPrefix: 'lightcase-',
|
|
classPrefix: 'lightcase-',
|
|
attrPrefix: 'lc-',
|
|
transition: 'elastic',
|
|
transitionOpen: null,
|
|
transitionClose: null,
|
|
transitionIn: null,
|
|
transitionOut: null,
|
|
cssTransitions: true,
|
|
speedIn: 250,
|
|
speedOut: 250,
|
|
width: null,
|
|
height: null,
|
|
maxWidth: 800,
|
|
maxHeight: 500,
|
|
forceWidth: false,
|
|
forceHeight: false,
|
|
liveResize: true,
|
|
fullScreenModeForMobile: true,
|
|
mobileMatchExpression: /(iphone|ipod|ipad|android|blackberry|symbian)/,
|
|
disableShrink: false,
|
|
fixedRatio: true,
|
|
shrinkFactor: .75,
|
|
overlayOpacity: .9,
|
|
slideshow: false,
|
|
slideshowAutoStart: true,
|
|
breakBeforeShow: false,
|
|
timeout: 5000,
|
|
swipe: true,
|
|
useKeys: true,
|
|
useCategories: true,
|
|
useAsCollection: false,
|
|
navigateEndless: true,
|
|
closeOnOverlayClick: true,
|
|
title: null,
|
|
caption: null,
|
|
showTitle: true,
|
|
showCaption: true,
|
|
showSequenceInfo: true,
|
|
inline: {
|
|
width: 'auto',
|
|
height: 'auto'
|
|
},
|
|
ajax: {
|
|
width: 'auto',
|
|
height: 'auto',
|
|
type: 'get',
|
|
dataType: 'html',
|
|
data: {}
|
|
},
|
|
iframe: {
|
|
width: 800,
|
|
height: 500,
|
|
frameborder: 0
|
|
},
|
|
flash: {
|
|
width: 400,
|
|
height: 205,
|
|
wmode: 'transparent'
|
|
},
|
|
video: {
|
|
width: 400,
|
|
height: 225,
|
|
poster: '',
|
|
preload: 'auto',
|
|
controls: true,
|
|
autobuffer: true,
|
|
autoplay: true,
|
|
loop: false
|
|
},
|
|
attr: 'data-rel',
|
|
href: null,
|
|
type: null,
|
|
typeMapping: {
|
|
'image': 'jpg,jpeg,gif,png,bmp',
|
|
'flash': 'swf',
|
|
'video': 'mp4,mov,ogv,ogg,webm',
|
|
'iframe': 'html,php',
|
|
'ajax': 'json,txt',
|
|
'inline': '#'
|
|
},
|
|
errorMessage: function () {
|
|
return '<p class="' + _self.settings.classPrefix + 'error">' + _self.settings.labels['errorMessage'] + '</p>';
|
|
},
|
|
labels: {
|
|
'errorMessage': 'Source could not be found...',
|
|
'sequenceInfo.of': ' of ',
|
|
'close': 'Close',
|
|
'navigator.prev': 'Prev',
|
|
'navigator.next': 'Next',
|
|
'navigator.play': 'Play',
|
|
'navigator.pause': 'Pause'
|
|
},
|
|
markup: function () {
|
|
_self.objects.body.append(
|
|
_self.objects.overlay = $('<div id="' + _self.settings.idPrefix + 'overlay"></div>'),
|
|
_self.objects.loading = $('<div id="' + _self.settings.idPrefix + 'loading" class="' + _self.settings.classPrefix + 'icon-spin"></div>'),
|
|
_self.objects.case = $('<div id="' + _self.settings.idPrefix + 'case" aria-hidden="true" role="dialog"></div>')
|
|
);
|
|
_self.objects.case.after(
|
|
_self.objects.close = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-close"><span>' + _self.settings.labels['close'] + '</span></a>'),
|
|
_self.objects.nav = $('<div id="' + _self.settings.idPrefix + 'nav"></div>')
|
|
);
|
|
_self.objects.nav.append(
|
|
_self.objects.prev = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-prev"><span>' + _self.settings.labels['navigator.prev'] + '</span></a>').hide(),
|
|
_self.objects.next = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-next"><span>' + _self.settings.labels['navigator.next'] + '</span></a>').hide(),
|
|
_self.objects.play = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-play"><span>' + _self.settings.labels['navigator.play'] + '</span></a>').hide(),
|
|
_self.objects.pause = $('<a href="#" class="' + _self.settings.classPrefix + 'icon-pause"><span>' + _self.settings.labels['navigator.pause'] + '</span></a>').hide()
|
|
);
|
|
_self.objects.case.append(
|
|
_self.objects.content = $('<div id="' + _self.settings.idPrefix + 'content"></div>'),
|
|
_self.objects.info = $('<div id="' + _self.settings.idPrefix + 'info"></div>')
|
|
);
|
|
_self.objects.content.append(
|
|
_self.objects.contentInner = $('<div class="' + _self.settings.classPrefix + 'contentInner"></div>')
|
|
);
|
|
_self.objects.info.append(
|
|
_self.objects.sequenceInfo = $('<div id="' + _self.settings.idPrefix + 'sequenceInfo"></div>'),
|
|
_self.objects.title = $('<h4 id="' + _self.settings.idPrefix + 'title"></h4>'),
|
|
_self.objects.caption = $('<p id="' + _self.settings.idPrefix + 'caption"></p>')
|
|
);
|
|
},
|
|
onInit: {},
|
|
onStart: {},
|
|
onBeforeCalculateDimensions: {},
|
|
onAfterCalculateDimensions: {},
|
|
onBeforeShow: {},
|
|
onFinish: {},
|
|
onResize: {},
|
|
onClose: {},
|
|
onCleanup: {}
|
|
},
|
|
options,
|
|
// Load options from data-lc-options attribute
|
|
_self.origin.data ? _self.origin.data('lc-options') : {});
|
|
|
|
_self.objects.document = $('html');
|
|
_self.objects.body = $('body');
|
|
|
|
// Call onInit hook functions
|
|
_self._callHooks(_self.settings.onInit);
|
|
|
|
_self.objectData = _self._setObjectData(this);
|
|
|
|
_self._addElements();
|
|
_self._open();
|
|
|
|
_self.dimensions = _self.getViewportDimensions();
|
|
},
|
|
|
|
/**
|
|
* Getter method for objects
|
|
*
|
|
* @param {string} name
|
|
* @return {object}
|
|
*/
|
|
get: function (name) {
|
|
return _self.objects[name];
|
|
},
|
|
|
|
/**
|
|
* Getter method for objectData
|
|
*
|
|
* @return {object}
|
|
*/
|
|
getObjectData: function () {
|
|
return _self.objectData;
|
|
},
|
|
|
|
/**
|
|
* Sets the object data
|
|
*
|
|
* @param {object} object
|
|
* @return {object} objectData
|
|
*/
|
|
_setObjectData: function (object) {
|
|
var $object = $(object),
|
|
objectData = {
|
|
this: $(object),
|
|
title: _self.settings.title || $object.attr(_self._prefixAttributeName('title')) || $object.attr('title'),
|
|
caption: _self.settings.caption || $object.attr(_self._prefixAttributeName('caption')) || $object.children('img').attr('alt'),
|
|
url: _self._determineUrl(),
|
|
requestType: _self.settings.ajax.type,
|
|
requestData: _self.settings.ajax.data,
|
|
requestDataType: _self.settings.ajax.dataType,
|
|
rel: $object.attr(_self._determineAttributeSelector()),
|
|
type: _self.settings.type || _self._verifyDataType(_self._determineUrl()),
|
|
isPartOfSequence: _self.settings.useAsCollection || _self._isPartOfSequence($object.attr(_self.settings.attr), ':'),
|
|
isPartOfSequenceWithSlideshow: _self._isPartOfSequence($object.attr(_self.settings.attr), ':slideshow'),
|
|
currentIndex: $(_self._determineAttributeSelector()).index($object),
|
|
sequenceLength: $(_self._determineAttributeSelector()).length
|
|
};
|
|
|
|
// Add sequence info to objectData
|
|
objectData.sequenceInfo = (objectData.currentIndex + 1) + _self.settings.labels['sequenceInfo.of'] + objectData.sequenceLength;
|
|
|
|
// Add next/prev index
|
|
objectData.prevIndex = objectData.currentIndex - 1;
|
|
objectData.nextIndex = objectData.currentIndex + 1;
|
|
|
|
return objectData;
|
|
},
|
|
|
|
/**
|
|
* Prefixes a data attribute name with defined name from 'settings.attrPrefix'
|
|
* to ensure more uniqueness for all lightcase related/used attributes.
|
|
*
|
|
* @param {string} name
|
|
* @return {string}
|
|
*/
|
|
_prefixAttributeName: function (name) {
|
|
return 'data-' + _self.settings.attrPrefix + name;
|
|
},
|
|
|
|
/**
|
|
* Determines the link target considering 'settings.href' and data attributes
|
|
* but also with a fallback to the default 'href' value.
|
|
*
|
|
* @return {string}
|
|
*/
|
|
_determineLinkTarget: function () {
|
|
return _self.settings.href || $(_self.origin).attr(_self._prefixAttributeName('href')) || $(_self.origin).attr('href');
|
|
},
|
|
|
|
/**
|
|
* Determines the attribute selector to use, depending on
|
|
* whether categorized collections are beeing used or not.
|
|
*
|
|
* @return {string} selector
|
|
*/
|
|
_determineAttributeSelector: function () {
|
|
var $origin = $(_self.origin),
|
|
selector = '';
|
|
|
|
if (typeof _self.cache.selector !== 'undefined') {
|
|
selector = _self.cache.selector;
|
|
} else if (_self.settings.useCategories === true && $origin.attr(_self._prefixAttributeName('categories'))) {
|
|
var categories = $origin.attr(_self._prefixAttributeName('categories')).split(' ');
|
|
|
|
$.each(categories, function (index, category) {
|
|
if (index > 0) {
|
|
selector += ',';
|
|
}
|
|
selector += '[' + _self._prefixAttributeName('categories') + '~="' + category + '"]';
|
|
});
|
|
} else {
|
|
selector = '[' + _self.settings.attr + '="' + $origin.attr(_self.settings.attr) + '"]';
|
|
}
|
|
|
|
_self.cache.selector = selector;
|
|
|
|
return selector;
|
|
},
|
|
|
|
/**
|
|
* Determines the correct resource according to the
|
|
* current viewport and density.
|
|
*
|
|
* @return {string} url
|
|
*/
|
|
_determineUrl: function () {
|
|
var dataUrl = _self._verifyDataUrl(_self._determineLinkTarget()),
|
|
width = 0,
|
|
density = 0,
|
|
supportLevel = '',
|
|
url;
|
|
|
|
$.each(dataUrl, function (index, src) {
|
|
switch (_self._verifyDataType(src.url)) {
|
|
case 'video':
|
|
var video = document.createElement('video'),
|
|
videoType = _self._verifyDataType(src.url) + '/' + _self._getFileUrlSuffix(src.url);
|
|
|
|
// Check if browser can play this type of video format
|
|
if (supportLevel !== 'probably' && supportLevel !== video.canPlayType(videoType) && video.canPlayType(videoType) !== '') {
|
|
supportLevel = video.canPlayType(videoType);
|
|
url = src.url;
|
|
}
|
|
break;
|
|
default:
|
|
if (
|
|
// Check density
|
|
_self._devicePixelRatio() >= src.density &&
|
|
src.density >= density &&
|
|
// Check viewport width
|
|
_self._matchMedia()('screen and (min-width:' + src.width + 'px)').matches &&
|
|
src.width >= width
|
|
) {
|
|
width = src.width;
|
|
density = src.density;
|
|
url = src.url;
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
|
|
return url;
|
|
},
|
|
|
|
/**
|
|
* Normalizes an url and returns information about the resource path,
|
|
* the viewport width as well as density if defined.
|
|
*
|
|
* @param {string} url Path to resource in format of an url or srcset
|
|
* @return {object}
|
|
*/
|
|
_normalizeUrl: function (url) {
|
|
var srcExp = /^\d+$/;
|
|
|
|
return url.split(',').map(function (str) {
|
|
var src = {
|
|
width: 0,
|
|
density: 0
|
|
};
|
|
|
|
str.trim().split(/\s+/).forEach(function (url, i) {
|
|
if (i === 0) {
|
|
return src.url = url;
|
|
}
|
|
|
|
var value = url.substring(0, url.length - 1),
|
|
lastChar = url[url.length - 1],
|
|
intVal = parseInt(value, 10),
|
|
floatVal = parseFloat(value);
|
|
if (lastChar === 'w' && srcExp.test(value)) {
|
|
src.width = intVal;
|
|
} else if (lastChar === 'h' && srcExp.test(value)) {
|
|
src.height = intVal;
|
|
} else if (lastChar === 'x' && !isNaN(floatVal)) {
|
|
src.density = floatVal;
|
|
}
|
|
});
|
|
|
|
return src;
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Verifies if the link is part of a sequence
|
|
*
|
|
* @param {string} rel
|
|
* @param {string} expression
|
|
* @return {boolean}
|
|
*/
|
|
_isPartOfSequence: function (rel, expression) {
|
|
var getSimilarLinks = $('[' + _self.settings.attr + '="' + rel + '"]'),
|
|
regexp = new RegExp(expression);
|
|
|
|
return (regexp.test(rel) && getSimilarLinks.length > 1);
|
|
},
|
|
|
|
/**
|
|
* Verifies if the slideshow should be enabled
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
isSlideshowEnabled: function () {
|
|
return (_self.objectData.isPartOfSequence && (_self.settings.slideshow === true || _self.objectData.isPartOfSequenceWithSlideshow === true));
|
|
},
|
|
|
|
/**
|
|
* Loads the new content to show
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_loadContent: function () {
|
|
if (_self.cache.originalObject) {
|
|
_self._restoreObject();
|
|
}
|
|
|
|
_self._createObject();
|
|
},
|
|
|
|
/**
|
|
* Creates a new object
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_createObject: function () {
|
|
var $object;
|
|
|
|
// Create object
|
|
switch (_self.objectData.type) {
|
|
case 'image':
|
|
$object = $(new Image());
|
|
$object.attr({
|
|
// The time expression is required to prevent the binding of an image load
|
|
'src': _self.objectData.url,
|
|
'alt': _self.objectData.title
|
|
});
|
|
break;
|
|
case 'inline':
|
|
$object = $('<div class="' + _self.settings.classPrefix + 'inlineWrap"></div>');
|
|
$object.html(_self._cloneObject($(_self.objectData.url)));
|
|
|
|
// Add custom attributes from _self.settings
|
|
$.each(_self.settings.inline, function (name, value) {
|
|
$object.attr(_self._prefixAttributeName(name), value);
|
|
});
|
|
break;
|
|
case 'ajax':
|
|
$object = $('<div class="' + _self.settings.classPrefix + 'inlineWrap"></div>');
|
|
|
|
// Add custom attributes from _self.settings
|
|
$.each(_self.settings.ajax, function (name, value) {
|
|
if (name !== 'data') {
|
|
$object.attr(_self._prefixAttributeName(name), value);
|
|
}
|
|
});
|
|
break;
|
|
case 'flash':
|
|
$object = $('<embed src="' + _self.objectData.url + '" type="application/x-shockwave-flash"></embed>');
|
|
|
|
// Add custom attributes from _self.settings
|
|
$.each(_self.settings.flash, function (name, value) {
|
|
$object.attr(name, value);
|
|
});
|
|
break;
|
|
case 'video':
|
|
$object = $('<video></video>');
|
|
$object.attr('src', _self.objectData.url);
|
|
|
|
// Add custom attributes from _self.settings
|
|
$.each(_self.settings.video, function (name, value) {
|
|
$object.attr(name, value);
|
|
});
|
|
break;
|
|
default:
|
|
$object = $('<iframe></iframe>');
|
|
$object.attr({
|
|
'src': _self.objectData.url
|
|
});
|
|
|
|
// Add custom attributes from _self.settings
|
|
$.each(_self.settings.iframe, function (name, value) {
|
|
$object.attr(name, value);
|
|
});
|
|
break;
|
|
}
|
|
|
|
_self._addObject($object);
|
|
_self._loadObject($object);
|
|
},
|
|
|
|
/**
|
|
* Adds the new object to the markup
|
|
*
|
|
* @param {object} $object
|
|
* @return {void}
|
|
*/
|
|
_addObject: function ($object) {
|
|
// Add object to content holder
|
|
_self.objects.contentInner.html($object);
|
|
|
|
// Start loading
|
|
_self._loading('start');
|
|
|
|
// Call onStart hook functions
|
|
_self._callHooks(_self.settings.onStart);
|
|
|
|
// Add sequenceInfo to the content holder or hide if its empty
|
|
if (_self.settings.showSequenceInfo === true && _self.objectData.isPartOfSequence) {
|
|
_self.objects.sequenceInfo.html(_self.objectData.sequenceInfo);
|
|
_self.objects.sequenceInfo.show();
|
|
} else {
|
|
_self.objects.sequenceInfo.empty();
|
|
_self.objects.sequenceInfo.hide();
|
|
}
|
|
// Add title to the content holder or hide if its empty
|
|
if (_self.settings.showTitle === true && _self.objectData.title !== undefined && _self.objectData.title !== '') {
|
|
_self.objects.title.html(_self.objectData.title);
|
|
_self.objects.title.show();
|
|
} else {
|
|
_self.objects.title.empty();
|
|
_self.objects.title.hide();
|
|
}
|
|
// Add caption to the content holder or hide if its empty
|
|
if (_self.settings.showCaption === true && _self.objectData.caption !== undefined && _self.objectData.caption !== '') {
|
|
_self.objects.caption.html(_self.objectData.caption);
|
|
_self.objects.caption.show();
|
|
} else {
|
|
_self.objects.caption.empty();
|
|
_self.objects.caption.hide();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Loads the new object
|
|
*
|
|
* @param {object} $object
|
|
* @return {void}
|
|
*/
|
|
_loadObject: function ($object) {
|
|
// Load the object
|
|
switch (_self.objectData.type) {
|
|
case 'inline':
|
|
if ($(_self.objectData.url)) {
|
|
_self._showContent($object);
|
|
} else {
|
|
_self.error();
|
|
}
|
|
break;
|
|
case 'ajax':
|
|
$.ajax(
|
|
$.extend({}, _self.settings.ajax, {
|
|
url: _self.objectData.url,
|
|
type: _self.objectData.requestType,
|
|
dataType: _self.objectData.requestDataType,
|
|
data: _self.objectData.requestData,
|
|
success: function (data, textStatus, jqXHR) {
|
|
// Check for X-Ajax-Location
|
|
if (jqXHR.getResponseHeader('X-Ajax-Location')) {
|
|
_self.objectData.url = jqXHR.getResponseHeader('X-Ajax-Location');
|
|
_self._loadObject($object);
|
|
}
|
|
else {
|
|
// Unserialize if data is transferred as json
|
|
if (_self.objectData.requestDataType === 'json') {
|
|
_self.objectData.data = data;
|
|
} else {
|
|
$object.html(data);
|
|
}
|
|
_self._showContent($object);
|
|
}
|
|
},
|
|
error: function (jqXHR, textStatus, errorThrown) {
|
|
_self.error();
|
|
}
|
|
})
|
|
);
|
|
break;
|
|
case 'flash':
|
|
_self._showContent($object);
|
|
break;
|
|
case 'video':
|
|
if (typeof($object.get(0).canPlayType) === 'function' || _self.objects.case.find('video').length === 0) {
|
|
_self._showContent($object);
|
|
} else {
|
|
_self.error();
|
|
}
|
|
break;
|
|
default:
|
|
if (_self.objectData.url) {
|
|
$object.on('load', function () {
|
|
_self._showContent($object);
|
|
});
|
|
$object.on('error', function () {
|
|
_self.error();
|
|
});
|
|
} else {
|
|
_self.error();
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Throws an error message if something went wrong
|
|
*
|
|
* @return {void}
|
|
*/
|
|
error: function () {
|
|
_self.objectData.type = 'error';
|
|
var $object = $('<div class="' + _self.settings.classPrefix + 'inlineWrap"></div>');
|
|
|
|
$object.html(_self.settings.errorMessage);
|
|
_self.objects.contentInner.html($object);
|
|
|
|
_self._showContent(_self.objects.contentInner);
|
|
},
|
|
|
|
/**
|
|
* Calculates the dimensions to fit content
|
|
*
|
|
* @param {object} $object
|
|
* @return {void}
|
|
*/
|
|
_calculateDimensions: function ($object) {
|
|
_self._cleanupDimensions();
|
|
|
|
if (!$object) return;
|
|
|
|
// Set default dimensions
|
|
var dimensions = {
|
|
ratio: 1,
|
|
objectWidth: $object.attr('width') ? $object.attr('width') : $object.attr(_self._prefixAttributeName('width')),
|
|
objectHeight: $object.attr('height') ? $object.attr('height') : $object.attr(_self._prefixAttributeName('height'))
|
|
};
|
|
|
|
if (!_self.settings.disableShrink) {
|
|
// Add calculated maximum width/height to dimensions
|
|
dimensions.maxWidth = parseInt(_self.dimensions.windowWidth * _self.settings.shrinkFactor);
|
|
dimensions.maxHeight = parseInt(_self.dimensions.windowHeight * _self.settings.shrinkFactor);
|
|
|
|
// If the auto calculated maxWidth/maxHeight greather than the user-defined one, use that.
|
|
if (dimensions.maxWidth > _self.settings.maxWidth) {
|
|
dimensions.maxWidth = _self.settings.maxWidth;
|
|
}
|
|
if (dimensions.maxHeight > _self.settings.maxHeight) {
|
|
dimensions.maxHeight = _self.settings.maxHeight;
|
|
}
|
|
|
|
// Calculate the difference between screen width/height and image width/height
|
|
dimensions.differenceWidthAsPercent = parseInt(100 / dimensions.maxWidth * dimensions.objectWidth);
|
|
dimensions.differenceHeightAsPercent = parseInt(100 / dimensions.maxHeight * dimensions.objectHeight);
|
|
|
|
switch (_self.objectData.type) {
|
|
case 'image':
|
|
case 'flash':
|
|
case 'video':
|
|
case 'iframe':
|
|
case 'ajax':
|
|
case 'inline':
|
|
if (_self.objectData.type === 'image' || _self.settings.fixedRatio === true) {
|
|
if (dimensions.differenceWidthAsPercent > 100 && dimensions.differenceWidthAsPercent > dimensions.differenceHeightAsPercent) {
|
|
dimensions.objectWidth = dimensions.maxWidth;
|
|
dimensions.objectHeight = parseInt(dimensions.objectHeight / dimensions.differenceWidthAsPercent * 100);
|
|
}
|
|
if (dimensions.differenceHeightAsPercent > 100 && dimensions.differenceHeightAsPercent > dimensions.differenceWidthAsPercent) {
|
|
dimensions.objectWidth = parseInt(dimensions.objectWidth / dimensions.differenceHeightAsPercent * 100);
|
|
dimensions.objectHeight = dimensions.maxHeight;
|
|
}
|
|
if (dimensions.differenceHeightAsPercent > 100 && dimensions.differenceWidthAsPercent < dimensions.differenceHeightAsPercent) {
|
|
dimensions.objectWidth = parseInt(dimensions.maxWidth / dimensions.differenceHeightAsPercent * dimensions.differenceWidthAsPercent);
|
|
dimensions.objectHeight = dimensions.maxHeight;
|
|
}
|
|
break;
|
|
}
|
|
case 'error':
|
|
if (!isNaN(dimensions.objectWidth) && dimensions.objectWidth > dimensions.maxWidth) {
|
|
dimensions.objectWidth = dimensions.maxWidth;
|
|
}
|
|
break;
|
|
default:
|
|
if ((isNaN(dimensions.objectWidth) || dimensions.objectWidth > dimensions.maxWidth) && !_self.settings.forceWidth) {
|
|
dimensions.objectWidth = dimensions.maxWidth;
|
|
}
|
|
if (((isNaN(dimensions.objectHeight) && dimensions.objectHeight !== 'auto') || dimensions.objectHeight > dimensions.maxHeight) && !_self.settings.forceHeight) {
|
|
dimensions.objectHeight = dimensions.maxHeight;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_self.settings.forceWidth) {
|
|
try {
|
|
dimensions.objectWidth = _self.settings[_self.objectData.type].width;
|
|
} catch (e) {
|
|
dimensions.objectWidth = _self.settings.width || dimensions.objectWidth;
|
|
}
|
|
|
|
dimensions.maxWidth = null;
|
|
}
|
|
if ($object.attr(_self._prefixAttributeName('max-width'))) {
|
|
dimensions.maxWidth = $object.attr(_self._prefixAttributeName('max-width'));
|
|
}
|
|
|
|
if (_self.settings.forceHeight) {
|
|
try {
|
|
dimensions.objectHeight = _self.settings[_self.objectData.type].height;
|
|
} catch (e) {
|
|
dimensions.objectHeight = _self.settings.height || dimensions.objectHeight;
|
|
}
|
|
|
|
dimensions.maxHeight = null;
|
|
}
|
|
if ($object.attr(_self._prefixAttributeName('max-height'))) {
|
|
dimensions.maxHeight = $object.attr(_self._prefixAttributeName('max-height'));
|
|
}
|
|
_self._adjustDimensions($object, dimensions);
|
|
},
|
|
|
|
/**
|
|
* Adjusts the dimensions
|
|
*
|
|
* @param {object} $object
|
|
* @param {object} dimensions
|
|
* @return {void}
|
|
*/
|
|
_adjustDimensions: function ($object, dimensions) {
|
|
// Adjust width and height
|
|
$object.css({
|
|
'width': dimensions.objectWidth,
|
|
'height': dimensions.objectHeight,
|
|
'max-width': dimensions.maxWidth,
|
|
'max-height': dimensions.maxHeight
|
|
});
|
|
|
|
_self.objects.contentInner.css({
|
|
'width': $object.outerWidth(),
|
|
'height': $object.outerHeight(),
|
|
'max-width': '100%'
|
|
});
|
|
|
|
_self.objects.case.css({
|
|
'width': _self.objects.contentInner.outerWidth(),
|
|
'max-width': '100%'
|
|
});
|
|
|
|
// Adjust margin
|
|
_self.objects.case.css({
|
|
'margin-top': parseInt(-(_self.objects.case.outerHeight() / 2)),
|
|
'margin-left': parseInt(-(_self.objects.case.outerWidth() / 2))
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Handles the _loading
|
|
*
|
|
* @param {string} process
|
|
* @return {void}
|
|
*/
|
|
_loading: function (process) {
|
|
if (process === 'start') {
|
|
_self.objects.case.addClass(_self.settings.classPrefix + 'loading');
|
|
_self.objects.loading.show();
|
|
} else if (process === 'end') {
|
|
_self.objects.case.removeClass(_self.settings.classPrefix + 'loading');
|
|
_self.objects.loading.hide();
|
|
}
|
|
},
|
|
|
|
|
|
/**
|
|
* Gets the client screen dimensions
|
|
*
|
|
* @return {object} dimensions
|
|
*/
|
|
getViewportDimensions: function () {
|
|
return {
|
|
windowWidth: $(window).innerWidth(),
|
|
windowHeight: $(window).innerHeight()
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Verifies the url
|
|
*
|
|
* @param {string} dataUrl
|
|
* @return {object} dataUrl Clean url for processing content
|
|
*/
|
|
_verifyDataUrl: function (dataUrl) {
|
|
if (!dataUrl || dataUrl === undefined || dataUrl === '') {
|
|
return false;
|
|
}
|
|
|
|
if (dataUrl.indexOf('#') > -1) {
|
|
dataUrl = dataUrl.split('#');
|
|
dataUrl = '#' + dataUrl[dataUrl.length - 1];
|
|
}
|
|
|
|
return _self._normalizeUrl(dataUrl.toString());
|
|
},
|
|
|
|
//
|
|
/**
|
|
* Tries to get the (file) suffix of an url
|
|
*
|
|
* @param {string} url
|
|
* @return {string}
|
|
*/
|
|
_getFileUrlSuffix: function (url) {
|
|
var re = /(?:\.([^.]+))?$/;
|
|
return re.exec(url.toLowerCase())[1];
|
|
},
|
|
|
|
/**
|
|
* Verifies the data type of the content to load
|
|
*
|
|
* @param {string} url
|
|
* @return {string|boolean} Array key if expression matched, else false
|
|
*/
|
|
_verifyDataType: function (url) {
|
|
var typeMapping = _self.settings.typeMapping;
|
|
|
|
// Early abort if dataUrl couldn't be verified
|
|
if (!url) {
|
|
return false;
|
|
}
|
|
|
|
// Verify the dataType of url according to typeMapping which
|
|
// has been defined in settings.
|
|
for (var key in typeMapping) {
|
|
if (typeMapping.hasOwnProperty(key)) {
|
|
var suffixArr = typeMapping[key].split(',');
|
|
|
|
for (var i = 0; i < suffixArr.length; i++) {
|
|
var suffix = suffixArr[i].toLowerCase(),
|
|
regexp = new RegExp('\.(' + suffix + ')$', 'i'),
|
|
str = url.toLowerCase().split('?')[0].substr(-5);
|
|
|
|
if (regexp.test(str) === true || (key === 'inline' && (url.indexOf(suffix) > -1))) {
|
|
return key;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If no expression matched, return 'iframe'.
|
|
return 'iframe';
|
|
},
|
|
|
|
/**
|
|
* Extends html markup with the essential tags
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_addElements: function () {
|
|
if (typeof _self.objects.case !== 'undefined' && $('#' + _self.objects.case.attr('id')).length) {
|
|
return;
|
|
}
|
|
|
|
_self.settings.markup();
|
|
},
|
|
|
|
/**
|
|
* Shows the loaded content
|
|
*
|
|
* @param {object} $object
|
|
* @return {void}
|
|
*/
|
|
_showContent: function ($object) {
|
|
// Add data attribute with the object type
|
|
_self.objects.document.attr(_self._prefixAttributeName('type'), _self.objectData.type);
|
|
|
|
_self.cache.object = $object;
|
|
|
|
// Call onBeforeShow hook functions
|
|
_self._callHooks(_self.settings.onBeforeShow);
|
|
|
|
if (_self.settings.breakBeforeShow) return;
|
|
_self.show();
|
|
},
|
|
|
|
/**
|
|
* Starts the 'inTransition'
|
|
* @return {void}
|
|
*/
|
|
_startInTransition: function () {
|
|
switch (_self.transition.in()) {
|
|
case 'scrollTop':
|
|
case 'scrollRight':
|
|
case 'scrollBottom':
|
|
case 'scrollLeft':
|
|
case 'scrollHorizontal':
|
|
case 'scrollVertical':
|
|
_self.transition.scroll(_self.objects.case, 'in', _self.settings.speedIn);
|
|
_self.transition.fade(_self.objects.contentInner, 'in', _self.settings.speedIn);
|
|
break;
|
|
case 'elastic':
|
|
if (_self.objects.case.css('opacity') < 1) {
|
|
_self.transition.zoom(_self.objects.case, 'in', _self.settings.speedIn);
|
|
_self.transition.fade(_self.objects.contentInner, 'in', _self.settings.speedIn);
|
|
}
|
|
case 'fade':
|
|
case 'fadeInline':
|
|
_self.transition.fade(_self.objects.case, 'in', _self.settings.speedIn);
|
|
_self.transition.fade(_self.objects.contentInner, 'in', _self.settings.speedIn);
|
|
break;
|
|
default:
|
|
_self.transition.fade(_self.objects.case, 'in', 0);
|
|
break;
|
|
}
|
|
|
|
// End loading.
|
|
_self._loading('end');
|
|
_self.isBusy = false;
|
|
|
|
// Set index of the first item opened
|
|
if (!_self.cache.firstOpened) {
|
|
_self.cache.firstOpened = _self.objectData.this;
|
|
}
|
|
|
|
// Fade in the info with delay
|
|
_self.objects.info.hide();
|
|
setTimeout(function () {
|
|
_self.transition.fade(_self.objects.info, 'in', _self.settings.speedIn);
|
|
}, _self.settings.speedIn);
|
|
|
|
// Call onFinish hook functions
|
|
_self._callHooks(_self.settings.onFinish);
|
|
},
|
|
|
|
/**
|
|
* Processes the content to show
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_processContent: function () {
|
|
_self.isBusy = true;
|
|
|
|
// Fade out the info at first
|
|
_self.transition.fade(_self.objects.info, 'out', 0);
|
|
|
|
switch (_self.settings.transitionOut) {
|
|
case 'scrollTop':
|
|
case 'scrollRight':
|
|
case 'scrollBottom':
|
|
case 'scrollLeft':
|
|
case 'scrollVertical':
|
|
case 'scrollHorizontal':
|
|
if (_self.objects.case.is(':hidden')) {
|
|
_self.transition.fade(_self.objects.contentInner, 'out', 0);
|
|
_self.transition.fade(_self.objects.case, 'out', 0, 0, function () {
|
|
_self._loadContent();
|
|
});
|
|
} else {
|
|
_self.transition.scroll(_self.objects.case, 'out', _self.settings.speedOut, function () {
|
|
_self._loadContent();
|
|
});
|
|
}
|
|
break;
|
|
case 'fade':
|
|
if (_self.objects.case.is(':hidden')) {
|
|
_self.transition.fade(_self.objects.case, 'out', 0, 0, function () {
|
|
_self._loadContent();
|
|
});
|
|
} else {
|
|
_self.transition.fade(_self.objects.case, 'out', _self.settings.speedOut, 0, function () {
|
|
_self._loadContent();
|
|
});
|
|
}
|
|
break;
|
|
case 'fadeInline':
|
|
case 'elastic':
|
|
if (_self.objects.case.is(':hidden')) {
|
|
_self.transition.fade(_self.objects.case, 'out', 0, 0, function () {
|
|
_self._loadContent();
|
|
});
|
|
} else {
|
|
_self.transition.fade(_self.objects.contentInner, 'out', _self.settings.speedOut, 0, function () {
|
|
_self._loadContent();
|
|
});
|
|
}
|
|
break;
|
|
default:
|
|
_self.transition.fade(_self.objects.case, 'out', 0, 0, function () {
|
|
_self._loadContent();
|
|
});
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles events for gallery buttons
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_handleEvents: function () {
|
|
_self._unbindEvents();
|
|
|
|
_self.objects.nav.children().not(_self.objects.close).hide();
|
|
|
|
// If slideshow is enabled, show play/pause and start timeout.
|
|
if (_self.isSlideshowEnabled()) {
|
|
// Only start the timeout if slideshow autostart is enabled and slideshow is not pausing
|
|
if (
|
|
(_self.settings.slideshowAutoStart === true || _self.isSlideshowStarted) &&
|
|
!_self.objects.nav.hasClass(_self.settings.classPrefix + 'paused')
|
|
) {
|
|
_self._startTimeout();
|
|
} else {
|
|
_self._stopTimeout();
|
|
}
|
|
}
|
|
|
|
if (_self.settings.liveResize) {
|
|
_self._watchResizeInteraction();
|
|
}
|
|
|
|
_self.objects.close.click(function (event) {
|
|
event.preventDefault();
|
|
_self.close();
|
|
});
|
|
|
|
if (_self.settings.closeOnOverlayClick === true) {
|
|
_self.objects.overlay.css('cursor', 'pointer').click(function (event) {
|
|
event.preventDefault();
|
|
|
|
_self.close();
|
|
});
|
|
}
|
|
|
|
if (_self.settings.useKeys === true) {
|
|
_self._addKeyEvents();
|
|
}
|
|
|
|
if (_self.objectData.isPartOfSequence) {
|
|
_self.objects.nav.attr(_self._prefixAttributeName('ispartofsequence'), true);
|
|
_self.objects.nav.data('items', _self._setNavigation());
|
|
|
|
_self.objects.prev.click(function (event) {
|
|
event.preventDefault();
|
|
|
|
if (_self.settings.navigateEndless === true || !_self.item.isFirst()) {
|
|
_self.objects.prev.unbind('click');
|
|
_self.cache.action = 'prev';
|
|
_self.objects.nav.data('items').prev.click();
|
|
|
|
if (_self.isSlideshowEnabled()) {
|
|
_self._stopTimeout();
|
|
}
|
|
}
|
|
});
|
|
|
|
_self.objects.next.click(function (event) {
|
|
event.preventDefault();
|
|
|
|
if (_self.settings.navigateEndless === true || !_self.item.isLast()) {
|
|
_self.objects.next.unbind('click');
|
|
_self.cache.action = 'next';
|
|
_self.objects.nav.data('items').next.click();
|
|
|
|
if (_self.isSlideshowEnabled()) {
|
|
_self._stopTimeout();
|
|
}
|
|
}
|
|
});
|
|
|
|
if (_self.isSlideshowEnabled()) {
|
|
_self.objects.play.click(function (event) {
|
|
event.preventDefault();
|
|
_self._startTimeout();
|
|
});
|
|
_self.objects.pause.click(function (event) {
|
|
event.preventDefault();
|
|
_self._stopTimeout();
|
|
});
|
|
}
|
|
|
|
// Enable swiping if activated
|
|
if (_self.settings.swipe === true) {
|
|
if ($.isPlainObject($.event.special.swipeleft)) {
|
|
_self.objects.case.on('swipeleft', function (event) {
|
|
event.preventDefault();
|
|
_self.objects.next.click();
|
|
if (_self.isSlideshowEnabled()) {
|
|
_self._stopTimeout();
|
|
}
|
|
});
|
|
}
|
|
if ($.isPlainObject($.event.special.swiperight)) {
|
|
_self.objects.case.on('swiperight', function (event) {
|
|
event.preventDefault();
|
|
_self.objects.prev.click();
|
|
if (_self.isSlideshowEnabled()) {
|
|
_self._stopTimeout();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adds the key events
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_addKeyEvents: function () {
|
|
$(document).bind('keyup.lightcase', function (event) {
|
|
// Do nothing if lightcase is in process
|
|
if (_self.isBusy) {
|
|
return;
|
|
}
|
|
|
|
switch (event.keyCode) {
|
|
// Escape key
|
|
case 27:
|
|
_self.objects.close.click();
|
|
break;
|
|
// Backward key
|
|
case 37:
|
|
if (_self.objectData.isPartOfSequence) {
|
|
_self.objects.prev.click();
|
|
}
|
|
break;
|
|
// Forward key
|
|
case 39:
|
|
if (_self.objectData.isPartOfSequence) {
|
|
_self.objects.next.click();
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Starts the slideshow timeout
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_startTimeout: function () {
|
|
_self.isSlideshowStarted = true;
|
|
|
|
_self.objects.play.hide();
|
|
_self.objects.pause.show();
|
|
|
|
_self.cache.action = 'next';
|
|
_self.objects.nav.removeClass(_self.settings.classPrefix + 'paused');
|
|
|
|
_self.timeout = setTimeout(function () {
|
|
_self.objects.nav.data('items').next.click();
|
|
}, _self.settings.timeout);
|
|
},
|
|
|
|
/**
|
|
* Stops the slideshow timeout
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_stopTimeout: function () {
|
|
_self.objects.play.show();
|
|
_self.objects.pause.hide();
|
|
|
|
_self.objects.nav.addClass(_self.settings.classPrefix + 'paused');
|
|
|
|
clearTimeout(_self.timeout);
|
|
},
|
|
|
|
/**
|
|
* Sets the navigator buttons (prev/next)
|
|
*
|
|
* @return {object} items
|
|
*/
|
|
_setNavigation: function () {
|
|
var $links = $((_self.cache.selector || _self.settings.attr)),
|
|
sequenceLength = _self.objectData.sequenceLength - 1,
|
|
items = {
|
|
prev: $links.eq(_self.objectData.prevIndex),
|
|
next: $links.eq(_self.objectData.nextIndex)
|
|
};
|
|
|
|
if (_self.objectData.currentIndex > 0) {
|
|
_self.objects.prev.show();
|
|
} else {
|
|
items.prevItem = $links.eq(sequenceLength);
|
|
}
|
|
if (_self.objectData.nextIndex <= sequenceLength) {
|
|
_self.objects.next.show();
|
|
} else {
|
|
items.next = $links.eq(0);
|
|
}
|
|
|
|
if (_self.settings.navigateEndless === true) {
|
|
_self.objects.prev.show();
|
|
_self.objects.next.show();
|
|
}
|
|
|
|
return items;
|
|
},
|
|
|
|
/**
|
|
* Item information/status
|
|
*
|
|
*/
|
|
item: {
|
|
/**
|
|
* Verifies if the current item is first item.
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
isFirst: function () {
|
|
return (_self.objectData.currentIndex === 0);
|
|
},
|
|
|
|
/**
|
|
* Verifies if the current item is first item opened.
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
isFirstOpened: function () {
|
|
return _self.objectData.this.is(_self.cache.firstOpened);
|
|
},
|
|
|
|
/**
|
|
* Verifies if the current item is last item.
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
isLast: function () {
|
|
return (_self.objectData.currentIndex === (_self.objectData.sequenceLength - 1));
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Clones the object for inline elements
|
|
*
|
|
* @param {object} $object
|
|
* @return {object} $clone
|
|
*/
|
|
_cloneObject: function ($object) {
|
|
var $clone = $object.clone(),
|
|
objectId = $object.attr('id');
|
|
|
|
// If element is hidden, cache the object and remove
|
|
if ($object.is(':hidden')) {
|
|
_self._cacheObjectData($object);
|
|
$object.attr('id', _self.settings.idPrefix + 'temp-' + objectId).empty();
|
|
} else {
|
|
// Prevent duplicated id's
|
|
$clone.removeAttr('id');
|
|
}
|
|
|
|
return $clone.show();
|
|
},
|
|
|
|
/**
|
|
* Verifies if it is a mobile device
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
isMobileDevice: function () {
|
|
var deviceAgent = navigator.userAgent.toLowerCase(),
|
|
agentId = deviceAgent.match(_self.settings.mobileMatchExpression);
|
|
|
|
return agentId ? true : false;
|
|
},
|
|
|
|
/**
|
|
* Verifies if css transitions are supported
|
|
*
|
|
* @return {string|boolean} The transition prefix if supported, else false.
|
|
*/
|
|
isTransitionSupported: function () {
|
|
var body = _self.objects.body.get(0),
|
|
isTransitionSupported = false,
|
|
transitionMapping = {
|
|
'transition': '',
|
|
'WebkitTransition': '-webkit-',
|
|
'MozTransition': '-moz-',
|
|
'OTransition': '-o-',
|
|
'MsTransition': '-ms-'
|
|
};
|
|
|
|
for (var key in transitionMapping) {
|
|
if (transitionMapping.hasOwnProperty(key) && key in body.style) {
|
|
_self.support.transition = transitionMapping[key];
|
|
isTransitionSupported = true;
|
|
}
|
|
}
|
|
|
|
return isTransitionSupported;
|
|
},
|
|
|
|
/**
|
|
* Transition types
|
|
*
|
|
*/
|
|
transition: {
|
|
/**
|
|
* Returns the correct transition type according to the status of interaction.
|
|
*
|
|
* @return {string} Transition type
|
|
*/
|
|
in: function () {
|
|
if (_self.settings.transitionOpen && !_self.cache.firstOpened) {
|
|
return _self.settings.transitionOpen;
|
|
}
|
|
return _self.settings.transitionIn;
|
|
},
|
|
|
|
/**
|
|
* Fades in/out the object
|
|
*
|
|
* @param {object} $object
|
|
* @param {string} type
|
|
* @param {number} speed
|
|
* @param {number} opacity
|
|
* @param {function} callback
|
|
* @return {void} Animates an object
|
|
*/
|
|
fade: function ($object, type, speed, opacity, callback) {
|
|
var isInTransition = type === 'in',
|
|
startTransition = {},
|
|
startOpacity = $object.css('opacity'),
|
|
endTransition = {},
|
|
endOpacity = opacity ? opacity: isInTransition ? 1 : 0;
|
|
|
|
if (!_self.isOpen && isInTransition) return;
|
|
|
|
startTransition['opacity'] = startOpacity;
|
|
endTransition['opacity'] = endOpacity;
|
|
|
|
$object.css(_self.support.transition + 'transition', 'none');
|
|
$object.css(startTransition).show();
|
|
|
|
// Css transition
|
|
if (_self.support.transitions) {
|
|
endTransition[_self.support.transition + 'transition'] = speed + 'ms ease';
|
|
|
|
setTimeout(function () {
|
|
$object.css(endTransition);
|
|
|
|
setTimeout(function () {
|
|
$object.css(_self.support.transition + 'transition', '');
|
|
|
|
if (callback && (_self.isOpen || !isInTransition)) {
|
|
callback();
|
|
}
|
|
}, speed);
|
|
}, 15);
|
|
} else {
|
|
// Fallback to js transition
|
|
$object.stop();
|
|
$object.animate(endTransition, speed, callback);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Scrolls in/out the object
|
|
*
|
|
* @param {object} $object
|
|
* @param {string} type
|
|
* @param {number} speed
|
|
* @param {function} callback
|
|
* @return {void} Animates an object
|
|
*/
|
|
scroll: function ($object, type, speed, callback) {
|
|
var isInTransition = type === 'in',
|
|
transition = isInTransition ? _self.settings.transitionIn : _self.settings.transitionOut,
|
|
direction = 'left',
|
|
startTransition = {},
|
|
startOpacity = isInTransition ? 0 : 1,
|
|
startOffset = isInTransition ? '-50%' : '50%',
|
|
endTransition = {},
|
|
endOpacity = isInTransition ? 1 : 0,
|
|
endOffset = isInTransition ? '50%' : '-50%';
|
|
|
|
if (!_self.isOpen && isInTransition) return;
|
|
|
|
switch (transition) {
|
|
case 'scrollTop':
|
|
direction = 'top';
|
|
break;
|
|
case 'scrollRight':
|
|
startOffset = isInTransition ? '150%' : '50%';
|
|
endOffset = isInTransition ? '50%' : '150%';
|
|
break;
|
|
case 'scrollBottom':
|
|
direction = 'top';
|
|
startOffset = isInTransition ? '150%' : '50%';
|
|
endOffset = isInTransition ? '50%' : '150%';
|
|
break;
|
|
case 'scrollHorizontal':
|
|
startOffset = isInTransition ? '150%' : '50%';
|
|
endOffset = isInTransition ? '50%' : '-50%';
|
|
break;
|
|
case 'scrollVertical':
|
|
direction = 'top';
|
|
startOffset = isInTransition ? '-50%' : '50%';
|
|
endOffset = isInTransition ? '50%' : '150%';
|
|
break;
|
|
}
|
|
|
|
if (_self.cache.action === 'prev') {
|
|
switch (transition) {
|
|
case 'scrollHorizontal':
|
|
startOffset = isInTransition ? '-50%' : '50%';
|
|
endOffset = isInTransition ? '50%' : '150%';
|
|
break;
|
|
case 'scrollVertical':
|
|
startOffset = isInTransition ? '150%' : '50%';
|
|
endOffset = isInTransition ? '50%' : '-50%';
|
|
break;
|
|
}
|
|
}
|
|
|
|
startTransition['opacity'] = startOpacity;
|
|
startTransition[direction] = startOffset;
|
|
|
|
endTransition['opacity'] = endOpacity;
|
|
endTransition[direction] = endOffset;
|
|
|
|
$object.css(_self.support.transition + 'transition', 'none');
|
|
$object.css(startTransition).show();
|
|
|
|
// Css transition
|
|
if (_self.support.transitions) {
|
|
endTransition[_self.support.transition + 'transition'] = speed + 'ms ease';
|
|
|
|
setTimeout(function () {
|
|
$object.css(endTransition);
|
|
|
|
setTimeout(function () {
|
|
$object.css(_self.support.transition + 'transition', '');
|
|
|
|
if (callback && (_self.isOpen || !isInTransition)) {
|
|
callback();
|
|
}
|
|
}, speed);
|
|
}, 15);
|
|
} else {
|
|
// Fallback to js transition
|
|
$object.stop();
|
|
$object.animate(endTransition, speed, callback);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Zooms in/out the object
|
|
*
|
|
* @param {object} $object
|
|
* @param {string} type
|
|
* @param {number} speed
|
|
* @param {function} callback
|
|
* @return {void} Animates an object
|
|
*/
|
|
zoom: function ($object, type, speed, callback) {
|
|
var isInTransition = type === 'in',
|
|
startTransition = {},
|
|
startOpacity = $object.css('opacity'),
|
|
startScale = isInTransition ? 'scale(0.75)' : 'scale(1)',
|
|
endTransition = {},
|
|
endOpacity = isInTransition ? 1 : 0,
|
|
endScale = isInTransition ? 'scale(1)' : 'scale(0.75)';
|
|
|
|
if (!_self.isOpen && isInTransition) return;
|
|
|
|
startTransition['opacity'] = startOpacity;
|
|
startTransition[_self.support.transition + 'transform'] = startScale;
|
|
|
|
endTransition['opacity'] = endOpacity;
|
|
|
|
$object.css(_self.support.transition + 'transition', 'none');
|
|
$object.css(startTransition).show();
|
|
|
|
// Css transition
|
|
if (_self.support.transitions) {
|
|
endTransition[_self.support.transition + 'transform'] = endScale;
|
|
endTransition[_self.support.transition + 'transition'] = speed + 'ms ease';
|
|
|
|
setTimeout(function () {
|
|
$object.css(endTransition);
|
|
|
|
setTimeout(function () {
|
|
$object.css(_self.support.transition + 'transform', '');
|
|
$object.css(_self.support.transition + 'transition', '');
|
|
|
|
if (callback && (_self.isOpen || !isInTransition)) {
|
|
callback();
|
|
}
|
|
}, speed);
|
|
}, 15);
|
|
} else {
|
|
// Fallback to js transition
|
|
$object.stop();
|
|
$object.animate(endTransition, speed, callback);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Calls all the registered functions of a specific hook
|
|
*
|
|
* @param {object} hooks
|
|
* @return {void}
|
|
*/
|
|
_callHooks: function (hooks) {
|
|
if (typeof(hooks) === 'object') {
|
|
$.each(hooks, function(index, hook) {
|
|
if (typeof(hook) === 'function') {
|
|
hook.call(_self.origin);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Caches the object data
|
|
*
|
|
* @param {object} $object
|
|
* @return {void}
|
|
*/
|
|
_cacheObjectData: function ($object) {
|
|
$.data($object, 'cache', {
|
|
id: $object.attr('id'),
|
|
content: $object.html()
|
|
});
|
|
|
|
_self.cache.originalObject = $object;
|
|
},
|
|
|
|
/**
|
|
* Restores the object from cache
|
|
*
|
|
* @return void
|
|
*/
|
|
_restoreObject: function () {
|
|
var $object = $('[id^="' + _self.settings.idPrefix + 'temp-"]');
|
|
|
|
$object.attr('id', $.data(_self.cache.originalObject, 'cache').id);
|
|
$object.html($.data(_self.cache.originalObject, 'cache').content);
|
|
},
|
|
|
|
/**
|
|
* Executes functions for a window resize.
|
|
* It stops an eventual timeout and recalculates dimensions.
|
|
*
|
|
* @param {object} dimensions
|
|
* @return {void}
|
|
*/
|
|
resize: function (event, dimensions) {
|
|
if (!_self.isOpen) return;
|
|
|
|
if (_self.isSlideshowEnabled()) {
|
|
_self._stopTimeout();
|
|
}
|
|
|
|
if (typeof dimensions === 'object' && dimensions !== null) {
|
|
if (dimensions.width) {
|
|
_self.cache.object.attr(
|
|
_self._prefixAttributeName('width'),
|
|
dimensions.width
|
|
);
|
|
}
|
|
if (dimensions.maxWidth) {
|
|
_self.cache.object.attr(
|
|
_self._prefixAttributeName('max-width'),
|
|
dimensions.maxWidth
|
|
);
|
|
}
|
|
if (dimensions.height) {
|
|
_self.cache.object.attr(
|
|
_self._prefixAttributeName('height'),
|
|
dimensions.height
|
|
);
|
|
}
|
|
if (dimensions.maxHeight) {
|
|
_self.cache.object.attr(
|
|
_self._prefixAttributeName('max-height'),
|
|
dimensions.maxHeight
|
|
);
|
|
}
|
|
}
|
|
|
|
_self.dimensions = _self.getViewportDimensions();
|
|
_self._calculateDimensions(_self.cache.object);
|
|
|
|
// Call onResize hook functions
|
|
_self._callHooks(_self.settings.onResize);
|
|
},
|
|
|
|
/**
|
|
* Watches for any resize interaction and caches the new sizes.
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_watchResizeInteraction: function () {
|
|
$(window).resize(_self.resize);
|
|
},
|
|
|
|
/**
|
|
* Stop watching any resize interaction related to _self.
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_unwatchResizeInteraction: function () {
|
|
$(window).off('resize', _self.resize);
|
|
},
|
|
|
|
/**
|
|
* Switches to the fullscreen mode
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_switchToFullScreenMode: function () {
|
|
_self.settings.shrinkFactor = 1;
|
|
_self.settings.overlayOpacity = 1;
|
|
|
|
$('html').addClass(_self.settings.classPrefix + 'fullScreenMode');
|
|
},
|
|
|
|
/**
|
|
* Enters into the lightcase view
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_open: function () {
|
|
_self.isOpen = true;
|
|
|
|
_self.support.transitions = _self.settings.cssTransitions ? _self.isTransitionSupported() : false;
|
|
_self.support.mobileDevice = _self.isMobileDevice();
|
|
|
|
if (_self.support.mobileDevice) {
|
|
$('html').addClass(_self.settings.classPrefix + 'isMobileDevice');
|
|
|
|
if (_self.settings.fullScreenModeForMobile) {
|
|
_self._switchToFullScreenMode();
|
|
}
|
|
}
|
|
|
|
if (!_self.settings.transitionIn) {
|
|
_self.settings.transitionIn = _self.settings.transition;
|
|
}
|
|
if (!_self.settings.transitionOut) {
|
|
_self.settings.transitionOut = _self.settings.transition;
|
|
}
|
|
|
|
switch (_self.transition.in()) {
|
|
case 'fade':
|
|
case 'fadeInline':
|
|
case 'elastic':
|
|
case 'scrollTop':
|
|
case 'scrollRight':
|
|
case 'scrollBottom':
|
|
case 'scrollLeft':
|
|
case 'scrollVertical':
|
|
case 'scrollHorizontal':
|
|
if (_self.objects.case.is(':hidden')) {
|
|
_self.objects.close.css('opacity', 0);
|
|
_self.objects.overlay.css('opacity', 0);
|
|
_self.objects.case.css('opacity', 0);
|
|
_self.objects.contentInner.css('opacity', 0);
|
|
}
|
|
_self.transition.fade(_self.objects.overlay, 'in', _self.settings.speedIn, _self.settings.overlayOpacity, function () {
|
|
_self.transition.fade(_self.objects.close, 'in', _self.settings.speedIn);
|
|
_self._handleEvents();
|
|
_self._processContent();
|
|
});
|
|
break;
|
|
default:
|
|
_self.transition.fade(_self.objects.overlay, 'in', 0, _self.settings.overlayOpacity, function () {
|
|
_self.transition.fade(_self.objects.close, 'in', 0);
|
|
_self._handleEvents();
|
|
_self._processContent();
|
|
});
|
|
break;
|
|
}
|
|
|
|
_self.objects.document.addClass(_self.settings.classPrefix + 'open');
|
|
_self.objects.case.attr('aria-hidden', 'false');
|
|
},
|
|
|
|
/**
|
|
* Shows the lightcase by starting the transition
|
|
*/
|
|
show: function () {
|
|
// Call onCalculateDimensions hook functions
|
|
_self._callHooks(_self.settings.onBeforeCalculateDimensions);
|
|
|
|
_self._calculateDimensions(_self.cache.object);
|
|
|
|
// Call onAfterCalculateDimensions hook functions
|
|
_self._callHooks(_self.settings.onAfterCalculateDimensions);
|
|
|
|
_self._startInTransition();
|
|
},
|
|
|
|
/**
|
|
* Escapes from the lightcase view
|
|
*
|
|
* @return {void}
|
|
*/
|
|
close: function () {
|
|
_self.isOpen = false;
|
|
|
|
if (_self.isSlideshowEnabled()) {
|
|
_self._stopTimeout();
|
|
_self.isSlideshowStarted = false;
|
|
_self.objects.nav.removeClass(_self.settings.classPrefix + 'paused');
|
|
}
|
|
|
|
_self.objects.loading.hide();
|
|
|
|
_self._unbindEvents();
|
|
|
|
_self._unwatchResizeInteraction();
|
|
|
|
$('html').removeClass(_self.settings.classPrefix + 'open');
|
|
_self.objects.case.attr('aria-hidden', 'true');
|
|
|
|
_self.objects.nav.children().hide();
|
|
_self.objects.close.hide();
|
|
|
|
// Call onClose hook functions
|
|
_self._callHooks(_self.settings.onClose);
|
|
|
|
// Fade out the info at first
|
|
_self.transition.fade(_self.objects.info, 'out', 0);
|
|
|
|
switch (_self.settings.transitionClose || _self.settings.transitionOut) {
|
|
case 'fade':
|
|
case 'fadeInline':
|
|
case 'scrollTop':
|
|
case 'scrollRight':
|
|
case 'scrollBottom':
|
|
case 'scrollLeft':
|
|
case 'scrollHorizontal':
|
|
case 'scrollVertical':
|
|
_self.transition.fade(_self.objects.case, 'out', _self.settings.speedOut, 0, function () {
|
|
_self.transition.fade(_self.objects.overlay, 'out', _self.settings.speedOut, 0, function () {
|
|
_self.cleanup();
|
|
});
|
|
});
|
|
break;
|
|
case 'elastic':
|
|
_self.transition.zoom(_self.objects.case, 'out', _self.settings.speedOut, function () {
|
|
_self.transition.fade(_self.objects.overlay, 'out', _self.settings.speedOut, 0, function () {
|
|
_self.cleanup();
|
|
});
|
|
});
|
|
break;
|
|
default:
|
|
_self.cleanup();
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Unbinds all given events
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_unbindEvents: function () {
|
|
// Unbind overlay event
|
|
_self.objects.overlay.unbind('click');
|
|
|
|
// Unbind key events
|
|
$(document).unbind('keyup.lightcase');
|
|
|
|
// Unbind swipe events
|
|
_self.objects.case.unbind('swipeleft').unbind('swiperight');
|
|
|
|
// Unbind navigator events
|
|
_self.objects.prev.unbind('click');
|
|
_self.objects.next.unbind('click');
|
|
_self.objects.play.unbind('click');
|
|
_self.objects.pause.unbind('click');
|
|
|
|
// Unbind close event
|
|
_self.objects.close.unbind('click');
|
|
},
|
|
|
|
/**
|
|
* Cleans up the dimensions
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_cleanupDimensions: function () {
|
|
var opacity = _self.objects.contentInner.css('opacity');
|
|
|
|
_self.objects.case.css({
|
|
'width': '',
|
|
'height': '',
|
|
'top': '',
|
|
'left': '',
|
|
'margin-top': '',
|
|
'margin-left': ''
|
|
});
|
|
|
|
_self.objects.contentInner.removeAttr('style').css('opacity', opacity);
|
|
_self.objects.contentInner.children().removeAttr('style');
|
|
},
|
|
|
|
/**
|
|
* Cleanup after aborting lightcase
|
|
*
|
|
* @return {void}
|
|
*/
|
|
cleanup: function () {
|
|
_self._cleanupDimensions();
|
|
|
|
_self.objects.loading.hide();
|
|
_self.objects.overlay.hide();
|
|
_self.objects.case.hide();
|
|
_self.objects.prev.hide();
|
|
_self.objects.next.hide();
|
|
_self.objects.play.hide();
|
|
_self.objects.pause.hide();
|
|
|
|
_self.objects.document.removeAttr(_self._prefixAttributeName('type'));
|
|
_self.objects.nav.removeAttr(_self._prefixAttributeName('ispartofsequence'));
|
|
|
|
_self.objects.contentInner.empty().hide();
|
|
_self.objects.info.children().empty();
|
|
|
|
if (_self.cache.originalObject) {
|
|
_self._restoreObject();
|
|
}
|
|
|
|
// Call onCleanup hook functions
|
|
_self._callHooks(_self.settings.onCleanup);
|
|
|
|
// Restore cache
|
|
_self.cache = {};
|
|
},
|
|
|
|
/**
|
|
* Returns the supported match media or undefined if the browser
|
|
* doesn't support match media.
|
|
*
|
|
* @return {mixed}
|
|
*/
|
|
_matchMedia: function () {
|
|
return window.matchMedia || window.msMatchMedia;
|
|
},
|
|
|
|
/**
|
|
* Returns the devicePixelRatio if supported. Else, it simply returns
|
|
* 1 as the default.
|
|
*
|
|
* @return {number}
|
|
*/
|
|
_devicePixelRatio: function () {
|
|
return window.devicePixelRatio || 1;
|
|
},
|
|
|
|
/**
|
|
* Checks if method is public
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
_isPublicMethod: function (method) {
|
|
return (typeof _self[method] === 'function' && method.charAt(0) !== '_');
|
|
},
|
|
|
|
/**
|
|
* Exports all public methods to be accessible, callable
|
|
* from global scope.
|
|
*
|
|
* @return {void}
|
|
*/
|
|
_export: function () {
|
|
window.lightcase = {};
|
|
|
|
$.each(_self, function (property) {
|
|
if (_self._isPublicMethod(property)) {
|
|
lightcase[property] = _self[property];
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
_self._export();
|
|
|
|
$.fn.lightcase = function (method) {
|
|
// Method calling logic (only public methods are applied)
|
|
if (_self._isPublicMethod(method)) {
|
|
return _self[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
|
} else if (typeof method === 'object' || !method) {
|
|
return _self.init.apply(this, arguments);
|
|
} else {
|
|
$.error('Method ' + method + ' does not exist on jQuery.lightcase');
|
|
}
|
|
};
|
|
})(jQuery);
|