3889 lines
128 KiB
JavaScript
Executable File
3889 lines
128 KiB
JavaScript
Executable File
/*!
|
||
* Fotorama 4.6.4 | http://fotorama.io/license/
|
||
*/
|
||
fotoramaVersion = '4.6.4';
|
||
(function (window, document, location, $, undefined) {
|
||
"use strict";
|
||
var _fotoramaClass = 'fotorama',
|
||
_fullscreenClass = 'fotorama__fullscreen',
|
||
|
||
wrapClass = _fotoramaClass + '__wrap',
|
||
wrapCss2Class = wrapClass + '--css2',
|
||
wrapCss3Class = wrapClass + '--css3',
|
||
wrapVideoClass = wrapClass + '--video',
|
||
wrapFadeClass = wrapClass + '--fade',
|
||
wrapSlideClass = wrapClass + '--slide',
|
||
wrapNoControlsClass = wrapClass + '--no-controls',
|
||
wrapNoShadowsClass = wrapClass + '--no-shadows',
|
||
wrapPanYClass = wrapClass + '--pan-y',
|
||
wrapRtlClass = wrapClass + '--rtl',
|
||
wrapOnlyActiveClass = wrapClass + '--only-active',
|
||
wrapNoCaptionsClass = wrapClass + '--no-captions',
|
||
wrapToggleArrowsClass = wrapClass + '--toggle-arrows',
|
||
|
||
stageClass = _fotoramaClass + '__stage',
|
||
stageFrameClass = stageClass + '__frame',
|
||
stageFrameVideoClass = stageFrameClass + '--video',
|
||
stageShaftClass = stageClass + '__shaft',
|
||
|
||
grabClass = _fotoramaClass + '__grab',
|
||
pointerClass = _fotoramaClass + '__pointer',
|
||
|
||
arrClass = _fotoramaClass + '__arr',
|
||
arrDisabledClass = arrClass + '--disabled',
|
||
arrPrevClass = arrClass + '--prev',
|
||
arrNextClass = arrClass + '--next',
|
||
|
||
navClass = _fotoramaClass + '__nav',
|
||
navWrapClass = navClass + '-wrap',
|
||
navShaftClass = navClass + '__shaft',
|
||
navShaftVerticalClass = navWrapClass + '--vertical',
|
||
navShaftListClass = navWrapClass + '--list',
|
||
navShafthorizontalClass = navWrapClass + '--horizontal',
|
||
navDotsClass = navClass + '--dots',
|
||
navThumbsClass = navClass + '--thumbs',
|
||
navFrameClass = navClass + '__frame',
|
||
|
||
fadeClass = _fotoramaClass + '__fade',
|
||
fadeFrontClass = fadeClass + '-front',
|
||
fadeRearClass = fadeClass + '-rear',
|
||
|
||
shadowClass = _fotoramaClass + '__shadow',
|
||
shadowsClass = shadowClass + 's',
|
||
shadowsLeftClass = shadowsClass + '--left',
|
||
shadowsRightClass = shadowsClass + '--right',
|
||
shadowsTopClass = shadowsClass + '--top',
|
||
shadowsBottomClass = shadowsClass + '--bottom',
|
||
|
||
activeClass = _fotoramaClass + '__active',
|
||
selectClass = _fotoramaClass + '__select',
|
||
|
||
hiddenClass = _fotoramaClass + '--hidden',
|
||
|
||
fullscreenClass = _fotoramaClass + '--fullscreen',
|
||
fullscreenIconClass = _fotoramaClass + '__fullscreen-icon',
|
||
|
||
errorClass = _fotoramaClass + '__error',
|
||
loadingClass = _fotoramaClass + '__loading',
|
||
loadedClass = _fotoramaClass + '__loaded',
|
||
loadedFullClass = loadedClass + '--full',
|
||
loadedImgClass = loadedClass + '--img',
|
||
|
||
grabbingClass = _fotoramaClass + '__grabbing',
|
||
|
||
imgClass = _fotoramaClass + '__img',
|
||
imgFullClass = imgClass + '--full',
|
||
|
||
thumbClass = _fotoramaClass + '__thumb',
|
||
thumbArrLeft = thumbClass + '__arr--left',
|
||
thumbArrRight = thumbClass + '__arr--right',
|
||
thumbBorderClass = thumbClass + '-border',
|
||
|
||
htmlClass = _fotoramaClass + '__html',
|
||
|
||
videoContainerClass = _fotoramaClass + '-video-container',
|
||
videoClass = _fotoramaClass + '__video',
|
||
videoPlayClass = videoClass + '-play',
|
||
videoCloseClass = videoClass + '-close',
|
||
|
||
|
||
horizontalImageClass = _fotoramaClass + '_horizontal_ratio',
|
||
verticalImageClass = _fotoramaClass + '_vertical_ratio',
|
||
fotoramaSpinnerClass = _fotoramaClass + '__spinner',
|
||
spinnerShowClass = fotoramaSpinnerClass + '--show';
|
||
var JQUERY_VERSION = $ && $.fn.jquery.split('.');
|
||
|
||
if (!JQUERY_VERSION
|
||
|| JQUERY_VERSION[0] < 1
|
||
|| (JQUERY_VERSION[0] == 1 && JQUERY_VERSION[1] < 8)) {
|
||
throw 'Fotorama requires jQuery 1.8 or later and will not run without it.';
|
||
}
|
||
|
||
var _ = {};
|
||
/* Modernizr 2.8.3 (Custom Build) | MIT & BSD
|
||
* Build: http://modernizr.com/download/#-csstransforms3d-csstransitions-touch-prefixed
|
||
*/
|
||
|
||
var Modernizr = (function (window, document, undefined) {
|
||
var version = '2.8.3',
|
||
Modernizr = {},
|
||
|
||
|
||
docElement = document.documentElement,
|
||
|
||
mod = 'modernizr',
|
||
modElem = document.createElement(mod),
|
||
mStyle = modElem.style,
|
||
inputElem,
|
||
|
||
|
||
toString = {}.toString,
|
||
|
||
prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
|
||
|
||
|
||
omPrefixes = 'Webkit Moz O ms',
|
||
|
||
cssomPrefixes = omPrefixes.split(' '),
|
||
|
||
domPrefixes = omPrefixes.toLowerCase().split(' '),
|
||
|
||
|
||
tests = {},
|
||
inputs = {},
|
||
attrs = {},
|
||
|
||
classes = [],
|
||
|
||
slice = classes.slice,
|
||
|
||
featureName,
|
||
|
||
|
||
injectElementWithStyles = function (rule, callback, nodes, testnames) {
|
||
|
||
var style, ret, node, docOverflow,
|
||
div = document.createElement('div'),
|
||
body = document.body,
|
||
fakeBody = body || document.createElement('body');
|
||
|
||
if (parseInt(nodes, 10)) {
|
||
while (nodes--) {
|
||
node = document.createElement('div');
|
||
node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
|
||
div.appendChild(node);
|
||
}
|
||
}
|
||
|
||
style = ['­', '<style id="s', mod, '">', rule, '</style>'].join('');
|
||
div.id = mod;
|
||
(body ? div : fakeBody).innerHTML += style;
|
||
fakeBody.appendChild(div);
|
||
if (!body) {
|
||
fakeBody.style.background = '';
|
||
fakeBody.style.overflow = 'hidden';
|
||
docOverflow = docElement.style.overflow;
|
||
docElement.style.overflow = 'hidden';
|
||
docElement.appendChild(fakeBody);
|
||
}
|
||
|
||
ret = callback(div, rule);
|
||
if (!body) {
|
||
fakeBody.parentNode.removeChild(fakeBody);
|
||
docElement.style.overflow = docOverflow;
|
||
} else {
|
||
div.parentNode.removeChild(div);
|
||
}
|
||
|
||
return !!ret;
|
||
|
||
},
|
||
_hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
|
||
|
||
if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) {
|
||
hasOwnProp = function (object, property) {
|
||
return _hasOwnProperty.call(object, property);
|
||
};
|
||
}
|
||
else {
|
||
hasOwnProp = function (object, property) {
|
||
return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
|
||
};
|
||
}
|
||
|
||
|
||
if (!Function.prototype.bind) {
|
||
Function.prototype.bind = function bind(that) {
|
||
|
||
var target = this;
|
||
|
||
if (typeof target != "function") {
|
||
throw new TypeError();
|
||
}
|
||
|
||
var args = slice.call(arguments, 1),
|
||
bound = function () {
|
||
|
||
if (this instanceof bound) {
|
||
|
||
var F = function () {
|
||
};
|
||
F.prototype = target.prototype;
|
||
var self = new F();
|
||
|
||
var result = target.apply(
|
||
self,
|
||
args.concat(slice.call(arguments))
|
||
);
|
||
if (Object(result) === result) {
|
||
return result;
|
||
}
|
||
return self;
|
||
|
||
} else {
|
||
|
||
return target.apply(
|
||
that,
|
||
args.concat(slice.call(arguments))
|
||
);
|
||
|
||
}
|
||
|
||
};
|
||
|
||
return bound;
|
||
};
|
||
}
|
||
|
||
function setCss(str) {
|
||
mStyle.cssText = str;
|
||
}
|
||
|
||
function setCssAll(str1, str2) {
|
||
return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
|
||
}
|
||
|
||
function is(obj, type) {
|
||
return typeof obj === type;
|
||
}
|
||
|
||
function contains(str, substr) {
|
||
return !!~('' + str).indexOf(substr);
|
||
}
|
||
|
||
function testProps(props, prefixed) {
|
||
for (var i in props) {
|
||
var prop = props[i];
|
||
if (!contains(prop, "-") && mStyle[prop] !== undefined) {
|
||
return prefixed == 'pfx' ? prop : true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
function testDOMProps(props, obj, elem) {
|
||
for (var i in props) {
|
||
var item = obj[props[i]];
|
||
if (item !== undefined) {
|
||
|
||
if (elem === false) return props[i];
|
||
|
||
if (is(item, 'function')) {
|
||
return item.bind(elem || obj);
|
||
}
|
||
|
||
return item;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
function testPropsAll(prop, prefixed, elem) {
|
||
|
||
var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
|
||
props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
|
||
|
||
if (is(prefixed, "string") || is(prefixed, "undefined")) {
|
||
return testProps(props, prefixed);
|
||
|
||
} else {
|
||
props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
|
||
return testDOMProps(props, prefixed, elem);
|
||
}
|
||
}
|
||
|
||
tests['touch'] = function () {
|
||
var bool;
|
||
|
||
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
|
||
bool = true;
|
||
} else {
|
||
injectElementWithStyles(['@media (', prefixes.join('touch-enabled),('), mod, ')', '{#modernizr{top:9px;position:absolute}}'].join(''), function (node) {
|
||
bool = node.offsetTop === 9;
|
||
});
|
||
}
|
||
|
||
return bool;
|
||
};
|
||
tests['csstransforms3d'] = function () {
|
||
|
||
var ret = !!testPropsAll('perspective');
|
||
|
||
if (ret && 'webkitPerspective' in docElement.style) {
|
||
|
||
injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function (node, rule) {
|
||
ret = node.offsetLeft === 9 && node.offsetHeight === 3;
|
||
});
|
||
}
|
||
return ret;
|
||
};
|
||
|
||
|
||
tests['csstransitions'] = function () {
|
||
return testPropsAll('transition');
|
||
};
|
||
|
||
|
||
for (var feature in tests) {
|
||
if (hasOwnProp(tests, feature)) {
|
||
featureName = feature.toLowerCase();
|
||
Modernizr[featureName] = tests[feature]();
|
||
|
||
classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
|
||
}
|
||
}
|
||
|
||
|
||
Modernizr.addTest = function (feature, test) {
|
||
if (typeof feature == 'object') {
|
||
for (var key in feature) {
|
||
if (hasOwnProp(feature, key)) {
|
||
Modernizr.addTest(key, feature[key]);
|
||
}
|
||
}
|
||
} else {
|
||
|
||
feature = feature.toLowerCase();
|
||
|
||
if (Modernizr[feature] !== undefined) {
|
||
return Modernizr;
|
||
}
|
||
|
||
test = typeof test == 'function' ? test() : test;
|
||
|
||
if (typeof enableClasses !== "undefined" && enableClasses) {
|
||
docElement.className += ' ' + (test ? '' : 'no-') + feature;
|
||
}
|
||
Modernizr[feature] = test;
|
||
|
||
}
|
||
|
||
return Modernizr;
|
||
};
|
||
|
||
|
||
setCss('');
|
||
modElem = inputElem = null;
|
||
|
||
|
||
Modernizr._version = version;
|
||
|
||
Modernizr._prefixes = prefixes;
|
||
Modernizr._domPrefixes = domPrefixes;
|
||
Modernizr._cssomPrefixes = cssomPrefixes;
|
||
|
||
|
||
Modernizr.testProp = function (prop) {
|
||
return testProps([prop]);
|
||
};
|
||
|
||
Modernizr.testAllProps = testPropsAll;
|
||
Modernizr.testStyles = injectElementWithStyles;
|
||
Modernizr.prefixed = function (prop, obj, elem) {
|
||
if (!obj) {
|
||
return testPropsAll(prop, 'pfx');
|
||
} else {
|
||
return testPropsAll(prop, obj, elem);
|
||
}
|
||
};
|
||
return Modernizr;
|
||
})(window, document);
|
||
|
||
var fullScreenApi = {
|
||
ok: false,
|
||
is: function () {
|
||
return false;
|
||
},
|
||
request: function () {
|
||
},
|
||
cancel: function () {
|
||
},
|
||
event: '',
|
||
prefix: ''
|
||
},
|
||
browserPrefixes = 'webkit moz o ms khtml'.split(' ');
|
||
|
||
// check for native support
|
||
if (typeof document.cancelFullScreen != 'undefined') {
|
||
fullScreenApi.ok = true;
|
||
} else {
|
||
// check for fullscreen support by vendor prefix
|
||
for (var i = 0, il = browserPrefixes.length; i < il; i++) {
|
||
fullScreenApi.prefix = browserPrefixes[i];
|
||
if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
|
||
fullScreenApi.ok = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// update methods to do something useful
|
||
if (fullScreenApi.ok) {
|
||
fullScreenApi.event = fullScreenApi.prefix + 'fullscreenchange';
|
||
fullScreenApi.is = function () {
|
||
switch (this.prefix) {
|
||
case '':
|
||
return document.fullScreen;
|
||
case 'webkit':
|
||
return document.webkitIsFullScreen;
|
||
default:
|
||
return document[this.prefix + 'FullScreen'];
|
||
}
|
||
};
|
||
fullScreenApi.request = function (el) {
|
||
return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
|
||
};
|
||
fullScreenApi.cancel = function (el) {
|
||
if (!this.is()) {
|
||
return false;
|
||
}
|
||
return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
|
||
};
|
||
}
|
||
/* Bez v1.0.10-g5ae0136
|
||
* http://github.com/rdallasgray/bez
|
||
*
|
||
* A plugin to convert CSS3 cubic-bezier co-ordinates to jQuery-compatible easing functions
|
||
*
|
||
* With thanks to Nikolay Nemshilov for clarification on the cubic-bezier maths
|
||
* See http://st-on-it.blogspot.com/2011/05/calculating-cubic-bezier-function.html
|
||
*
|
||
* Copyright 2011 Robert Dallas Gray. All rights reserved.
|
||
* Provided under the FreeBSD license: https://github.com/rdallasgray/bez/blob/master/LICENSE.txt
|
||
*/
|
||
function bez(coOrdArray) {
|
||
var encodedFuncName = "bez_" + $.makeArray(arguments).join("_").replace(".", "p");
|
||
if (typeof $['easing'][encodedFuncName] !== "function") {
|
||
var polyBez = function (p1, p2) {
|
||
var A = [null, null],
|
||
B = [null, null],
|
||
C = [null, null],
|
||
bezCoOrd = function (t, ax) {
|
||
C[ax] = 3 * p1[ax];
|
||
B[ax] = 3 * (p2[ax] - p1[ax]) - C[ax];
|
||
A[ax] = 1 - C[ax] - B[ax];
|
||
return t * (C[ax] + t * (B[ax] + t * A[ax]));
|
||
},
|
||
xDeriv = function (t) {
|
||
return C[0] + t * (2 * B[0] + 3 * A[0] * t);
|
||
},
|
||
xForT = function (t) {
|
||
var x = t, i = 0, z;
|
||
while (++i < 14) {
|
||
z = bezCoOrd(x, 0) - t;
|
||
if (Math.abs(z) < 1e-3) break;
|
||
x -= z / xDeriv(x);
|
||
}
|
||
return x;
|
||
};
|
||
return function (t) {
|
||
return bezCoOrd(xForT(t), 1);
|
||
}
|
||
};
|
||
$['easing'][encodedFuncName] = function (x, t, b, c, d) {
|
||
return c * polyBez([coOrdArray[0], coOrdArray[1]], [coOrdArray[2], coOrdArray[3]])(t / d) + b;
|
||
}
|
||
}
|
||
return encodedFuncName;
|
||
}
|
||
|
||
var $WINDOW = $(window),
|
||
$DOCUMENT = $(document),
|
||
$HTML,
|
||
$BODY,
|
||
|
||
QUIRKS_FORCE = location.hash.replace('#', '') === 'quirks',
|
||
TRANSFORMS3D = Modernizr.csstransforms3d,
|
||
CSS3 = TRANSFORMS3D && !QUIRKS_FORCE,
|
||
COMPAT = TRANSFORMS3D || document.compatMode === 'CSS1Compat',
|
||
FULLSCREEN = fullScreenApi.ok,
|
||
|
||
MOBILE = navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i),
|
||
SLOW = !CSS3 || MOBILE,
|
||
|
||
MS_POINTER = navigator.msPointerEnabled,
|
||
|
||
WHEEL = "onwheel" in document.createElement("div") ? "wheel" : document.onmousewheel !== undefined ? "mousewheel" : "DOMMouseScroll",
|
||
|
||
TOUCH_TIMEOUT = 250,
|
||
TRANSITION_DURATION = 300,
|
||
|
||
SCROLL_LOCK_TIMEOUT = 1400,
|
||
|
||
AUTOPLAY_INTERVAL = 5000,
|
||
MARGIN = 2,
|
||
THUMB_SIZE = 64,
|
||
|
||
WIDTH = 500,
|
||
HEIGHT = 333,
|
||
|
||
STAGE_FRAME_KEY = '$stageFrame',
|
||
NAV_DOT_FRAME_KEY = '$navDotFrame',
|
||
NAV_THUMB_FRAME_KEY = '$navThumbFrame',
|
||
|
||
AUTO = 'auto',
|
||
|
||
BEZIER = bez([.1, 0, .25, 1]),
|
||
|
||
MAX_WIDTH = 1200,
|
||
|
||
/**
|
||
* Number of thumbnails in slide. Calculated only on setOptions and resize.
|
||
* @type {number}
|
||
*/
|
||
thumbsPerSlide = 1,
|
||
|
||
OPTIONS = {
|
||
|
||
/**
|
||
* Set width for gallery.
|
||
* Default value - width of first image
|
||
* Number - set value in px
|
||
* String - set value in quotes
|
||
*
|
||
*/
|
||
width: null,
|
||
|
||
/**
|
||
* Set min-width for gallery
|
||
*
|
||
*/
|
||
minwidth: null,
|
||
|
||
/**
|
||
* Set max-width for gallery
|
||
*
|
||
*/
|
||
maxwidth: '100%',
|
||
|
||
/**
|
||
* Set height for gallery
|
||
* Default value - height of first image
|
||
* Number - set value in px
|
||
* String - set value in quotes
|
||
*
|
||
*/
|
||
height: null,
|
||
|
||
/**
|
||
* Set min-height for gallery
|
||
*
|
||
*/
|
||
minheight: null,
|
||
|
||
/**
|
||
* Set max-height for gallery
|
||
*
|
||
*/
|
||
maxheight: null,
|
||
|
||
/**
|
||
* Set proportion ratio for gallery depends of image
|
||
*
|
||
*/
|
||
ratio: null, // '16/9' || 500/333 || 1.5
|
||
|
||
margin: MARGIN,
|
||
|
||
nav: 'dots', // 'thumbs' || false
|
||
navposition: 'bottom', // 'top'
|
||
navwidth: null,
|
||
thumbwidth: THUMB_SIZE,
|
||
thumbheight: THUMB_SIZE,
|
||
thumbmargin: MARGIN,
|
||
thumbborderwidth: MARGIN,
|
||
|
||
allowfullscreen: false, // true || 'native'
|
||
|
||
transition: 'slide', // 'crossfade' || 'dissolve'
|
||
clicktransition: null,
|
||
transitionduration: TRANSITION_DURATION,
|
||
|
||
captions: true,
|
||
|
||
startindex: 0,
|
||
|
||
loop: false,
|
||
|
||
autoplay: false,
|
||
stopautoplayontouch: true,
|
||
|
||
keyboard: false,
|
||
|
||
arrows: true,
|
||
click: true,
|
||
swipe: false,
|
||
trackpad: false,
|
||
|
||
shuffle: false,
|
||
|
||
direction: 'ltr', // 'rtl'
|
||
|
||
shadows: true,
|
||
|
||
showcaption: true,
|
||
|
||
/**
|
||
* Set type of thumbnail navigation
|
||
*/
|
||
navdir: 'horizontal',
|
||
|
||
/**
|
||
* Set configuration to show or hide arrows in thumb navigation
|
||
*/
|
||
navarrows: true,
|
||
|
||
/**
|
||
* Set type of navigation. Can be thumbs or slides
|
||
*/
|
||
navtype: 'thumbs'
|
||
|
||
},
|
||
|
||
KEYBOARD_OPTIONS = {
|
||
left: true,
|
||
right: true,
|
||
down: true,
|
||
up: true,
|
||
space: false,
|
||
home: false,
|
||
end: false
|
||
};
|
||
|
||
function noop() {
|
||
}
|
||
|
||
function minMaxLimit(value, min, max) {
|
||
return Math.max(isNaN(min) ? -Infinity : min, Math.min(isNaN(max) ? Infinity : max, value));
|
||
}
|
||
|
||
function readTransform(css, dir) {
|
||
return css.match(/ma/) && css.match(/-?\d+(?!d)/g)[css.match(/3d/) ?
|
||
(dir === 'vertical' ? 13 : 12) : (dir === 'vertical' ? 5 : 4)
|
||
]
|
||
}
|
||
|
||
function readPosition($el, dir) {
|
||
if (CSS3) {
|
||
return +readTransform($el.css('transform'), dir);
|
||
} else {
|
||
return +$el.css(dir === 'vertical' ? 'top' : 'left').replace('px', '');
|
||
}
|
||
}
|
||
|
||
function getTranslate(pos, direction) {
|
||
var obj = {};
|
||
|
||
if (CSS3) {
|
||
|
||
switch (direction) {
|
||
case 'vertical':
|
||
obj.transform = 'translate3d(0, ' + (pos) + 'px,0)';
|
||
break;
|
||
case 'list':
|
||
break;
|
||
default :
|
||
obj.transform = 'translate3d(' + (pos) + 'px,0,0)';
|
||
break;
|
||
}
|
||
} else {
|
||
direction === 'vertical' ?
|
||
obj.top = pos :
|
||
obj.left = pos;
|
||
}
|
||
return obj;
|
||
}
|
||
|
||
function getDuration(time) {
|
||
return {'transition-duration': time + 'ms'};
|
||
}
|
||
|
||
function unlessNaN(value, alternative) {
|
||
return isNaN(value) ? alternative : value;
|
||
}
|
||
|
||
function numberFromMeasure(value, measure) {
|
||
return unlessNaN(+String(value).replace(measure || 'px', ''));
|
||
}
|
||
|
||
function numberFromPercent(value) {
|
||
return /%$/.test(value) ? numberFromMeasure(value, '%') : undefined;
|
||
}
|
||
|
||
function numberFromWhatever(value, whole) {
|
||
return unlessNaN(numberFromPercent(value) / 100 * whole, numberFromMeasure(value));
|
||
}
|
||
|
||
function measureIsValid(value) {
|
||
return (!isNaN(numberFromMeasure(value)) || !isNaN(numberFromMeasure(value, '%'))) && value;
|
||
}
|
||
|
||
function getPosByIndex(index, side, margin, baseIndex) {
|
||
|
||
return (index - (baseIndex || 0)) * (side + (margin || 0));
|
||
}
|
||
|
||
function getIndexByPos(pos, side, margin, baseIndex) {
|
||
return -Math.round(pos / (side + (margin || 0)) - (baseIndex || 0));
|
||
}
|
||
|
||
function bindTransitionEnd($el) {
|
||
var elData = $el.data();
|
||
|
||
if (elData.tEnd) return;
|
||
|
||
var el = $el[0],
|
||
transitionEndEvent = {
|
||
WebkitTransition: 'webkitTransitionEnd',
|
||
MozTransition: 'transitionend',
|
||
OTransition: 'oTransitionEnd otransitionend',
|
||
msTransition: 'MSTransitionEnd',
|
||
transition: 'transitionend'
|
||
};
|
||
addEvent(el, transitionEndEvent[Modernizr.prefixed('transition')], function (e) {
|
||
elData.tProp && e.propertyName.match(elData.tProp) && elData.onEndFn();
|
||
});
|
||
elData.tEnd = true;
|
||
}
|
||
|
||
function afterTransition($el, property, fn, time) {
|
||
var ok,
|
||
elData = $el.data();
|
||
|
||
if (elData) {
|
||
elData.onEndFn = function () {
|
||
if (ok) return;
|
||
ok = true;
|
||
clearTimeout(elData.tT);
|
||
fn();
|
||
};
|
||
elData.tProp = property;
|
||
|
||
// Passive call, just in case of fail of native transition-end event
|
||
clearTimeout(elData.tT);
|
||
elData.tT = setTimeout(function () {
|
||
elData.onEndFn();
|
||
}, time * 1.5);
|
||
|
||
bindTransitionEnd($el);
|
||
}
|
||
}
|
||
|
||
|
||
function stop($el, pos/*, _001*/) {
|
||
var dir = $el.navdir || 'horizontal';
|
||
if ($el.length) {
|
||
var elData = $el.data();
|
||
if (CSS3) {
|
||
$el.css(getDuration(0));
|
||
elData.onEndFn = noop;
|
||
clearTimeout(elData.tT);
|
||
} else {
|
||
$el.stop();
|
||
}
|
||
var lockedPos = getNumber(pos, function () {
|
||
return readPosition($el, dir);
|
||
});
|
||
|
||
$el.css(getTranslate(lockedPos, dir/*, _001*/));//.width(); // `.width()` for reflow
|
||
return lockedPos;
|
||
}
|
||
}
|
||
|
||
function getNumber() {
|
||
var number;
|
||
for (var _i = 0, _l = arguments.length; _i < _l; _i++) {
|
||
number = _i ? arguments[_i]() : arguments[_i];
|
||
if (typeof number === 'number') {
|
||
break;
|
||
}
|
||
}
|
||
|
||
return number;
|
||
}
|
||
|
||
function edgeResistance(pos, edge) {
|
||
return Math.round(pos + ((edge - pos) / 1.5));
|
||
}
|
||
|
||
function getProtocol() {
|
||
getProtocol.p = getProtocol.p || (location.protocol === 'https:' ? 'https://' : 'http://');
|
||
return getProtocol.p;
|
||
}
|
||
|
||
function parseHref(href) {
|
||
var a = document.createElement('a');
|
||
a.href = href;
|
||
return a;
|
||
}
|
||
|
||
function findVideoId(href, forceVideo) {
|
||
if (typeof href !== 'string') return href;
|
||
href = parseHref(href);
|
||
|
||
var id,
|
||
type;
|
||
|
||
if (href.host.match(/youtube\.com/) && href.search) {
|
||
//.log();
|
||
id = href.search.split('v=')[1];
|
||
if (id) {
|
||
var ampersandPosition = id.indexOf('&');
|
||
if (ampersandPosition !== -1) {
|
||
id = id.substring(0, ampersandPosition);
|
||
}
|
||
type = 'youtube';
|
||
}
|
||
} else if (href.host.match(/youtube\.com|youtu\.be|youtube-nocookie.com/)) {
|
||
id = href.pathname.replace(/^\/(embed\/|v\/)?/, '').replace(/\/.*/, '');
|
||
type = 'youtube';
|
||
} else if (href.host.match(/vimeo\.com/)) {
|
||
type = 'vimeo';
|
||
id = href.pathname.replace(/^\/(video\/)?/, '').replace(/\/.*/, '');
|
||
}
|
||
|
||
if ((!id || !type) && forceVideo) {
|
||
id = href.href;
|
||
type = 'custom';
|
||
}
|
||
|
||
return id ? {id: id, type: type, s: href.search.replace(/^\?/, ''), p: getProtocol()} : false;
|
||
}
|
||
|
||
function getVideoThumbs(dataFrame, data, fotorama) {
|
||
var img, thumb, video = dataFrame.video;
|
||
if (video.type === 'youtube') {
|
||
thumb = getProtocol() + 'img.youtube.com/vi/' + video.id + '/default.jpg';
|
||
img = thumb.replace(/\/default.jpg$/, '/hqdefault.jpg');
|
||
dataFrame.thumbsReady = true;
|
||
} else if (video.type === 'vimeo') {
|
||
$.ajax({
|
||
url: getProtocol() + 'vimeo.com/api/oembed.json',
|
||
data: {
|
||
url: 'https://vimeo.com/' + video.id
|
||
},
|
||
dataType: 'jsonp',
|
||
success: function (json) {
|
||
dataFrame.thumbsReady = true;
|
||
updateData(data, {
|
||
img: json[0].thumbnail_url,
|
||
thumb: json[0].thumbnail_url
|
||
}, dataFrame.i, fotorama);
|
||
}
|
||
});
|
||
} else {
|
||
dataFrame.thumbsReady = true;
|
||
}
|
||
|
||
return {
|
||
img: img,
|
||
thumb: thumb
|
||
}
|
||
}
|
||
|
||
function updateData(data, _dataFrame, i, fotorama) {
|
||
for (var _i = 0, _l = data.length; _i < _l; _i++) {
|
||
var dataFrame = data[_i];
|
||
|
||
if (dataFrame.i === i && dataFrame.thumbsReady) {
|
||
var clear = {videoReady: true};
|
||
clear[STAGE_FRAME_KEY] = clear[NAV_THUMB_FRAME_KEY] = clear[NAV_DOT_FRAME_KEY] = false;
|
||
|
||
fotorama.splice(_i, 1, $.extend(
|
||
{},
|
||
dataFrame,
|
||
clear,
|
||
_dataFrame
|
||
));
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
function getDataFromHtml($el) {
|
||
var data = [];
|
||
|
||
function getDataFromImg($img, imgData, checkVideo) {
|
||
var $child = $img.children('img').eq(0),
|
||
_imgHref = $img.attr('href'),
|
||
_imgSrc = $img.attr('src'),
|
||
_thumbSrc = $child.attr('src'),
|
||
_video = imgData.video,
|
||
video = checkVideo ? findVideoId(_imgHref, _video === true) : false;
|
||
|
||
if (video) {
|
||
_imgHref = false;
|
||
} else {
|
||
video = _video;
|
||
}
|
||
|
||
getDimensions($img, $child, $.extend(imgData, {
|
||
video: video,
|
||
img: imgData.img || _imgHref || _imgSrc || _thumbSrc,
|
||
thumb: imgData.thumb || _thumbSrc || _imgSrc || _imgHref
|
||
}));
|
||
}
|
||
|
||
function getDimensions($img, $child, imgData) {
|
||
var separateThumbFLAG = imgData.thumb && imgData.img !== imgData.thumb,
|
||
width = numberFromMeasure(imgData.width || $img.attr('width')),
|
||
height = numberFromMeasure(imgData.height || $img.attr('height'));
|
||
|
||
$.extend(imgData, {
|
||
width: width,
|
||
height: height,
|
||
thumbratio: getRatio(imgData.thumbratio || (numberFromMeasure(imgData.thumbwidth || ($child && $child.attr('width')) || separateThumbFLAG || width) / numberFromMeasure(imgData.thumbheight || ($child && $child.attr('height')) || separateThumbFLAG || height)))
|
||
});
|
||
}
|
||
|
||
$el.children().each(function () {
|
||
var $this = $(this),
|
||
dataFrame = optionsToLowerCase($.extend($this.data(), {id: $this.attr('id')}));
|
||
if ($this.is('a, img')) {
|
||
getDataFromImg($this, dataFrame, true);
|
||
} else if (!$this.is(':empty')) {
|
||
getDimensions($this, null, $.extend(dataFrame, {
|
||
html: this,
|
||
_html: $this.html() // Because of IE
|
||
}));
|
||
} else return;
|
||
|
||
data.push(dataFrame);
|
||
});
|
||
|
||
return data;
|
||
}
|
||
|
||
function isHidden(el) {
|
||
return el.offsetWidth === 0 && el.offsetHeight === 0;
|
||
}
|
||
|
||
function isDetached(el) {
|
||
return !$.contains(document.documentElement, el);
|
||
}
|
||
|
||
function waitFor(test, fn, timeout, i) {
|
||
if (!waitFor.i) {
|
||
waitFor.i = 1;
|
||
waitFor.ii = [true];
|
||
}
|
||
|
||
i = i || waitFor.i;
|
||
|
||
if (typeof waitFor.ii[i] === 'undefined') {
|
||
waitFor.ii[i] = true;
|
||
}
|
||
|
||
if (test()) {
|
||
fn();
|
||
} else {
|
||
waitFor.ii[i] && setTimeout(function () {
|
||
waitFor.ii[i] && waitFor(test, fn, timeout, i);
|
||
}, timeout || 100);
|
||
}
|
||
|
||
return waitFor.i++;
|
||
}
|
||
|
||
waitFor.stop = function (i) {
|
||
waitFor.ii[i] = false;
|
||
};
|
||
|
||
function fit($el, measuresToFit) {
|
||
var elData = $el.data(),
|
||
measures = elData.measures;
|
||
|
||
if (measures && (!elData.l ||
|
||
elData.l.W !== measures.width ||
|
||
elData.l.H !== measures.height ||
|
||
elData.l.r !== measures.ratio ||
|
||
elData.l.w !== measuresToFit.w ||
|
||
elData.l.h !== measuresToFit.h)) {
|
||
|
||
var height = minMaxLimit(measuresToFit.h, 0, measures.height),
|
||
width = height * measures.ratio;
|
||
|
||
UTIL.setRatio($el, width, height);
|
||
|
||
elData.l = {
|
||
W: measures.width,
|
||
H: measures.height,
|
||
r: measures.ratio,
|
||
w: measuresToFit.w,
|
||
h: measuresToFit.h
|
||
};
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
function setStyle($el, style) {
|
||
var el = $el[0];
|
||
if (el.styleSheet) {
|
||
el.styleSheet.cssText = style;
|
||
} else {
|
||
$el.html(style);
|
||
}
|
||
}
|
||
|
||
function findShadowEdge(pos, min, max, dir) {
|
||
return min === max ? false :
|
||
dir === 'vertical' ?
|
||
(pos <= min ? 'top' : pos >= max ? 'bottom' : 'top bottom') :
|
||
(pos <= min ? 'left' : pos >= max ? 'right' : 'left right');
|
||
}
|
||
|
||
function smartClick($el, fn, _options) {
|
||
_options = _options || {};
|
||
|
||
$el.each(function () {
|
||
var $this = $(this),
|
||
thisData = $this.data(),
|
||
startEvent;
|
||
|
||
if (thisData.clickOn) return;
|
||
|
||
thisData.clickOn = true;
|
||
|
||
$.extend(touch($this, {
|
||
onStart: function (e) {
|
||
startEvent = e;
|
||
(_options.onStart || noop).call(this, e);
|
||
},
|
||
onMove: _options.onMove || noop,
|
||
onTouchEnd: _options.onTouchEnd || noop,
|
||
onEnd: function (result) {
|
||
if (result.moved) return;
|
||
fn.call(this, startEvent);
|
||
}
|
||
}), {noMove: true});
|
||
});
|
||
}
|
||
|
||
function div(classes, child) {
|
||
return '<div class="' + classes + '">' + (child || '') + '</div>';
|
||
}
|
||
|
||
|
||
/**
|
||
* Function transforming into valid classname
|
||
* @param className - name of the class
|
||
* @returns {string} - dom format of class name
|
||
*/
|
||
function cls(className) {
|
||
return "." + className;
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param {json-object} videoItem Parsed object from data.video item or href from link a in input dates
|
||
* @returns {string} DOM view of video iframe
|
||
*/
|
||
function createVideoFrame(videoItem) {
|
||
var frame = '<iframe src="' + videoItem.p + videoItem.type + '.com/embed/' + videoItem.id + '" frameborder="0" allowfullscreen></iframe>';
|
||
return frame;
|
||
}
|
||
|
||
// Fisher–Yates Shuffle
|
||
// http://bost.ocks.org/mike/shuffle/
|
||
function shuffle(array) {
|
||
// While there remain elements to shuffle
|
||
var l = array.length;
|
||
while (l) {
|
||
// Pick a remaining element
|
||
var i = Math.floor(Math.random() * l--);
|
||
|
||
// And swap it with the current element
|
||
var t = array[l];
|
||
array[l] = array[i];
|
||
array[i] = t;
|
||
}
|
||
|
||
return array;
|
||
}
|
||
|
||
function clone(array) {
|
||
return Object.prototype.toString.call(array) == '[object Array]'
|
||
&& $.map(array, function (frame) {
|
||
return $.extend({}, frame);
|
||
});
|
||
}
|
||
|
||
function lockScroll($el, left, top) {
|
||
$el
|
||
.scrollLeft(left || 0)
|
||
.scrollTop(top || 0);
|
||
}
|
||
|
||
function optionsToLowerCase(options) {
|
||
if (options) {
|
||
var opts = {};
|
||
$.each(options, function (key, value) {
|
||
opts[key.toLowerCase()] = value;
|
||
});
|
||
|
||
return opts;
|
||
}
|
||
}
|
||
|
||
function getRatio(_ratio) {
|
||
if (!_ratio) return;
|
||
var ratio = +_ratio;
|
||
if (!isNaN(ratio)) {
|
||
return ratio;
|
||
} else {
|
||
ratio = _ratio.split('/');
|
||
return +ratio[0] / +ratio[1] || undefined;
|
||
}
|
||
}
|
||
|
||
function addEvent(el, e, fn, bool) {
|
||
if (!e) return;
|
||
el.addEventListener ? el.addEventListener(e, fn, !!bool) : el.attachEvent('on' + e, fn);
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param position guess position for navShaft
|
||
* @param restriction object contains min and max values for position
|
||
* @returns {*} filtered value of position
|
||
*/
|
||
function validateRestrictions(position, restriction) {
|
||
if (position > restriction.max) {
|
||
position = restriction.max;
|
||
} else {
|
||
if (position < restriction.min) {
|
||
position = restriction.min;
|
||
}
|
||
}
|
||
return position;
|
||
}
|
||
|
||
function validateSlidePos(opt, navShaftTouchTail, guessIndex, offsetNav, $guessNavFrame, $navWrap, dir) {
|
||
var position,
|
||
size,
|
||
wrapSize;
|
||
if (dir === 'horizontal') {
|
||
size = opt.thumbwidth;
|
||
wrapSize = $navWrap.width();
|
||
} else {
|
||
size = opt.thumbheight;
|
||
wrapSize = $navWrap.height();
|
||
}
|
||
if ( (size + opt.margin) * (guessIndex + 1) >= (wrapSize - offsetNav) ) {
|
||
if (dir === 'horizontal') {
|
||
position = -$guessNavFrame.position().left;
|
||
} else {
|
||
position = -$guessNavFrame.position().top;
|
||
}
|
||
} else {
|
||
if ((size + opt.margin) * (guessIndex) <= Math.abs(offsetNav)) {
|
||
if (dir === 'horizontal') {
|
||
position = -$guessNavFrame.position().left + wrapSize - (size + opt.margin);
|
||
} else {
|
||
position = -$guessNavFrame.position().top + wrapSize - (size + opt.margin);
|
||
}
|
||
} else {
|
||
position = offsetNav;
|
||
}
|
||
}
|
||
position = validateRestrictions(position, navShaftTouchTail);
|
||
|
||
return position || 0;
|
||
}
|
||
|
||
function elIsDisabled(el) {
|
||
return !!el.getAttribute('disabled');
|
||
}
|
||
|
||
function disableAttr(FLAG, disable) {
|
||
if (disable) {
|
||
return {disabled: FLAG};
|
||
} else {
|
||
return {tabindex: FLAG * -1 + '', disabled: FLAG};
|
||
|
||
}
|
||
}
|
||
|
||
function addEnterUp(el, fn) {
|
||
addEvent(el, 'keyup', function (e) {
|
||
elIsDisabled(el) || e.keyCode == 13 && fn.call(el, e);
|
||
});
|
||
}
|
||
|
||
function addFocus(el, fn) {
|
||
addEvent(el, 'focus', el.onfocusin = function (e) {
|
||
fn.call(el, e);
|
||
}, true);
|
||
}
|
||
|
||
function stopEvent(e, stopPropagation) {
|
||
e.preventDefault ? e.preventDefault() : (e.returnValue = false);
|
||
stopPropagation && e.stopPropagation && e.stopPropagation();
|
||
}
|
||
|
||
function getDirectionSign(forward) {
|
||
return forward ? '>' : '<';
|
||
}
|
||
|
||
var UTIL = (function () {
|
||
|
||
function setRatioClass($el, wh, ht) {
|
||
var rateImg = wh / ht;
|
||
|
||
if (rateImg <= 1) {
|
||
$el.parent().removeClass(horizontalImageClass);
|
||
$el.parent().addClass(verticalImageClass);
|
||
} else {
|
||
$el.parent().removeClass(verticalImageClass);
|
||
$el.parent().addClass(horizontalImageClass);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Set specific attribute in thumbnail template
|
||
* @param $frame DOM item of specific thumbnail
|
||
* @param value Value which must be setted into specific attribute
|
||
* @param searchAttr Name of attribute where value must be included
|
||
*/
|
||
function setThumbAttr($frame, value, searchAttr) {
|
||
var attr = searchAttr;
|
||
|
||
if (!$frame.attr(attr) && $frame.attr(attr) !== undefined) {
|
||
$frame.attr(attr, value);
|
||
}
|
||
|
||
if ($frame.find("[" + attr + "]").length) {
|
||
$frame.find("[" + attr + "]")
|
||
.each(function () {
|
||
$(this).attr(attr, value);
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Method describe behavior need to render caption on preview or not
|
||
* @param frameItem specific item from data
|
||
* @param isExpected {bool} if items with caption need render them or not
|
||
* @returns {boolean} if true then caption should be rendered
|
||
*/
|
||
function isExpectedCaption(frameItem, isExpected, undefined) {
|
||
var expected = false,
|
||
frameExpected;
|
||
|
||
frameItem.showCaption === undefined || frameItem.showCaption === true ? frameExpected = true : frameExpected = false;
|
||
|
||
if (!isExpected) {
|
||
return false;
|
||
}
|
||
|
||
if (frameItem.caption && frameExpected) {
|
||
expected = true;
|
||
}
|
||
|
||
return expected;
|
||
}
|
||
|
||
return {
|
||
setRatio: setRatioClass,
|
||
setThumbAttr: setThumbAttr,
|
||
isExpectedCaption: isExpectedCaption
|
||
};
|
||
|
||
}(UTIL || {}, jQuery));
|
||
|
||
function slide($el, options) {
|
||
var elData = $el.data(),
|
||
elPos = Math.round(options.pos),
|
||
onEndFn = function () {
|
||
if (elData && elData.sliding) {
|
||
elData.sliding = false;
|
||
}
|
||
(options.onEnd || noop)();
|
||
};
|
||
|
||
if (typeof options.overPos !== 'undefined' && options.overPos !== options.pos) {
|
||
elPos = options.overPos;
|
||
}
|
||
|
||
var translate = $.extend(getTranslate(elPos, options.direction), options.width && {width: options.width}, options.height && {height: options.height});
|
||
if (elData && elData.sliding) {
|
||
elData.sliding = true;
|
||
}
|
||
|
||
if (CSS3) {
|
||
$el.css($.extend(getDuration(options.time), translate));
|
||
|
||
if (options.time > 10) {
|
||
afterTransition($el, 'transform', onEndFn, options.time);
|
||
} else {
|
||
onEndFn();
|
||
}
|
||
} else {
|
||
$el.stop().animate(translate, options.time, BEZIER, onEndFn);
|
||
}
|
||
}
|
||
|
||
function fade($el1, $el2, $frames, options, fadeStack, chain) {
|
||
var chainedFLAG = typeof chain !== 'undefined';
|
||
if (!chainedFLAG) {
|
||
fadeStack.push(arguments);
|
||
Array.prototype.push.call(arguments, fadeStack.length);
|
||
if (fadeStack.length > 1) return;
|
||
}
|
||
|
||
$el1 = $el1 || $($el1);
|
||
$el2 = $el2 || $($el2);
|
||
|
||
var _$el1 = $el1[0],
|
||
_$el2 = $el2[0],
|
||
crossfadeFLAG = options.method === 'crossfade',
|
||
onEndFn = function () {
|
||
if (!onEndFn.done) {
|
||
onEndFn.done = true;
|
||
var args = (chainedFLAG || fadeStack.shift()) && fadeStack.shift();
|
||
args && fade.apply(this, args);
|
||
(options.onEnd || noop)(!!args);
|
||
}
|
||
},
|
||
time = options.time / (chain || 1);
|
||
|
||
$frames.removeClass(fadeRearClass + ' ' + fadeFrontClass);
|
||
|
||
$el1
|
||
.stop()
|
||
.addClass(fadeRearClass);
|
||
$el2
|
||
.stop()
|
||
.addClass(fadeFrontClass);
|
||
|
||
crossfadeFLAG && _$el2 && $el1.fadeTo(0, 0);
|
||
|
||
$el1.fadeTo(crossfadeFLAG ? time : 0, 1, crossfadeFLAG && onEndFn);
|
||
$el2.fadeTo(time, 0, onEndFn);
|
||
|
||
(_$el1 && crossfadeFLAG) || _$el2 || onEndFn();
|
||
}
|
||
|
||
var lastEvent,
|
||
moveEventType,
|
||
preventEvent,
|
||
preventEventTimeout,
|
||
dragDomEl;
|
||
|
||
function extendEvent(e) {
|
||
var touch = (e.touches || [])[0] || e;
|
||
e._x = touch.pageX || touch.originalEvent.pageX;
|
||
e._y = touch.clientY || touch.originalEvent.clientY;
|
||
e._now = $.now();
|
||
}
|
||
|
||
function touch($el, options) {
|
||
var el = $el[0],
|
||
tail = {},
|
||
touchEnabledFLAG,
|
||
startEvent,
|
||
$target,
|
||
controlTouch,
|
||
touchFLAG,
|
||
targetIsSelectFLAG,
|
||
targetIsLinkFlag,
|
||
isDisabledSwipe,
|
||
tolerance,
|
||
moved;
|
||
|
||
function onStart(e) {
|
||
$target = $(e.target);
|
||
tail.checked = targetIsSelectFLAG = targetIsLinkFlag = isDisabledSwipe = moved = false;
|
||
|
||
if (touchEnabledFLAG
|
||
|| tail.flow
|
||
|| (e.touches && e.touches.length > 1)
|
||
|| e.which > 1
|
||
|| (lastEvent && lastEvent.type !== e.type && preventEvent)
|
||
|| (targetIsSelectFLAG = options.select && $target.is(options.select, el))) return targetIsSelectFLAG;
|
||
|
||
touchFLAG = e.type === 'touchstart';
|
||
targetIsLinkFlag = $target.is('a, a *', el);
|
||
isDisabledSwipe = $target.hasClass('disableSwipe');
|
||
controlTouch = tail.control;
|
||
|
||
tolerance = (tail.noMove || tail.noSwipe || controlTouch) ? 16 : !tail.snap ? 4 : 0;
|
||
|
||
extendEvent(e);
|
||
|
||
startEvent = lastEvent = e;
|
||
moveEventType = e.type.replace(/down|start/, 'move').replace(/Down/, 'Move');
|
||
|
||
(options.onStart || noop).call(el, e, {control: controlTouch, $target: $target});
|
||
|
||
touchEnabledFLAG = tail.flow = true;
|
||
|
||
if (!isDisabledSwipe && (!touchFLAG || tail.go)) stopEvent(e);
|
||
}
|
||
|
||
function onMove(e) {
|
||
if ((e.touches && e.touches.length > 1)
|
||
|| (MS_POINTER && !e.isPrimary)
|
||
|| moveEventType !== e.type
|
||
|| !touchEnabledFLAG) {
|
||
touchEnabledFLAG && onEnd();
|
||
(options.onTouchEnd || noop)();
|
||
return;
|
||
}
|
||
|
||
isDisabledSwipe = $(e.target).hasClass('disableSwipe');
|
||
|
||
if (isDisabledSwipe) {
|
||
return;
|
||
}
|
||
|
||
extendEvent(e);
|
||
|
||
var xDiff = Math.abs(e._x - startEvent._x), // opt _x → _pageX
|
||
yDiff = Math.abs(e._y - startEvent._y),
|
||
xyDiff = xDiff - yDiff,
|
||
xWin = (tail.go || tail.x || xyDiff >= 0) && !tail.noSwipe,
|
||
yWin = xyDiff < 0;
|
||
|
||
if (touchFLAG && !tail.checked) {
|
||
if (touchEnabledFLAG = xWin) {
|
||
stopEvent(e);
|
||
}
|
||
} else {
|
||
stopEvent(e);
|
||
if (movedEnough(xDiff,yDiff)) {
|
||
(options.onMove || noop).call(el, e, {touch: touchFLAG});
|
||
}
|
||
}
|
||
|
||
if (!moved && movedEnough(xDiff, yDiff) && Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2)) > tolerance) {
|
||
moved = true;
|
||
}
|
||
|
||
tail.checked = tail.checked || xWin || yWin;
|
||
}
|
||
|
||
function movedEnough(xDiff, yDiff) {
|
||
return xDiff > yDiff && xDiff > 1.5;
|
||
}
|
||
|
||
function onEnd(e) {
|
||
(options.onTouchEnd || noop)();
|
||
|
||
var _touchEnabledFLAG = touchEnabledFLAG;
|
||
tail.control = touchEnabledFLAG = false;
|
||
|
||
if (_touchEnabledFLAG) {
|
||
tail.flow = false;
|
||
}
|
||
|
||
if (!_touchEnabledFLAG || (targetIsLinkFlag && !tail.checked)) return;
|
||
|
||
e && stopEvent(e);
|
||
|
||
preventEvent = true;
|
||
clearTimeout(preventEventTimeout);
|
||
preventEventTimeout = setTimeout(function () {
|
||
preventEvent = false;
|
||
}, 1000);
|
||
|
||
(options.onEnd || noop).call(el, {
|
||
moved: moved,
|
||
$target: $target,
|
||
control: controlTouch,
|
||
touch: touchFLAG,
|
||
startEvent: startEvent,
|
||
aborted: !e || e.type === 'MSPointerCancel'
|
||
});
|
||
}
|
||
|
||
function onOtherStart() {
|
||
if (tail.flow) return;
|
||
tail.flow = true;
|
||
}
|
||
|
||
function onOtherEnd() {
|
||
if (!tail.flow) return;
|
||
tail.flow = false;
|
||
}
|
||
|
||
if (MS_POINTER) {
|
||
addEvent(el, 'MSPointerDown', onStart);
|
||
addEvent(document, 'MSPointerMove', onMove);
|
||
addEvent(document, 'MSPointerCancel', onEnd);
|
||
addEvent(document, 'MSPointerUp', onEnd);
|
||
} else {
|
||
addEvent(el, 'touchstart', onStart);
|
||
addEvent(el, 'touchmove', onMove);
|
||
addEvent(el, 'touchend', onEnd);
|
||
|
||
addEvent(document, 'touchstart', onOtherStart, true);
|
||
addEvent(document, 'touchend', onOtherEnd);
|
||
addEvent(document, 'touchcancel', onOtherEnd);
|
||
|
||
$WINDOW.on('scroll', onOtherEnd);
|
||
|
||
$el.on('mousedown', onStart);
|
||
$DOCUMENT
|
||
.on('mousemove', onMove)
|
||
.on('mouseup', onEnd);
|
||
}
|
||
if (Modernizr.touch) {
|
||
dragDomEl = 'a';
|
||
} else {
|
||
dragDomEl = 'div';
|
||
}
|
||
$el.on('click', dragDomEl, function (e) {
|
||
tail.checked && stopEvent(e);
|
||
});
|
||
|
||
return tail;
|
||
}
|
||
|
||
function moveOnTouch($el, options) {
|
||
var el = $el[0],
|
||
elData = $el.data(),
|
||
tail = {},
|
||
startCoo,
|
||
coo,
|
||
startElPos,
|
||
moveElPos,
|
||
edge,
|
||
moveTrack,
|
||
startTime,
|
||
endTime,
|
||
min,
|
||
max,
|
||
snap,
|
||
dir,
|
||
slowFLAG,
|
||
controlFLAG,
|
||
moved,
|
||
tracked;
|
||
|
||
function startTracking(e, noStop) {
|
||
tracked = true;
|
||
startCoo = coo = (dir === 'vertical') ? e._y : e._x;
|
||
startTime = e._now;
|
||
|
||
moveTrack = [
|
||
[startTime, startCoo]
|
||
];
|
||
|
||
startElPos = moveElPos = tail.noMove || noStop ? 0 : stop($el, (options.getPos || noop)()/*, options._001*/);
|
||
|
||
(options.onStart || noop).call(el, e);
|
||
}
|
||
|
||
function onStart(e, result) {
|
||
min = tail.min;
|
||
max = tail.max;
|
||
snap = tail.snap,
|
||
dir = tail.direction || 'horizontal',
|
||
$el.navdir = dir;
|
||
|
||
slowFLAG = e.altKey;
|
||
tracked = moved = false;
|
||
|
||
controlFLAG = result.control;
|
||
|
||
if (!controlFLAG && !elData.sliding) {
|
||
startTracking(e);
|
||
}
|
||
}
|
||
|
||
function onMove(e, result) {
|
||
if (!tail.noSwipe) {
|
||
if (!tracked) {
|
||
startTracking(e);
|
||
}
|
||
coo = (dir === 'vertical') ? e._y : e._x;
|
||
|
||
moveTrack.push([e._now, coo]);
|
||
|
||
moveElPos = startElPos - (startCoo - coo);
|
||
|
||
edge = findShadowEdge(moveElPos, min, max, dir);
|
||
|
||
if (moveElPos <= min) {
|
||
moveElPos = edgeResistance(moveElPos, min);
|
||
} else if (moveElPos >= max) {
|
||
moveElPos = edgeResistance(moveElPos, max);
|
||
}
|
||
|
||
if (!tail.noMove) {
|
||
$el.css(getTranslate(moveElPos, dir));
|
||
if (!moved) {
|
||
moved = true;
|
||
// only for mouse
|
||
result.touch || MS_POINTER || $el.addClass(grabbingClass);
|
||
}
|
||
|
||
(options.onMove || noop).call(el, e, {pos: moveElPos, edge: edge});
|
||
}
|
||
}
|
||
}
|
||
|
||
function onEnd(result) {
|
||
if (tail.noSwipe && result.moved) return;
|
||
|
||
if (!tracked) {
|
||
startTracking(result.startEvent, true);
|
||
}
|
||
|
||
result.touch || MS_POINTER || $el.removeClass(grabbingClass);
|
||
|
||
endTime = $.now();
|
||
|
||
var _backTimeIdeal = endTime - TOUCH_TIMEOUT,
|
||
_backTime,
|
||
_timeDiff,
|
||
_timeDiffLast,
|
||
backTime = null,
|
||
backCoo,
|
||
virtualPos,
|
||
limitPos,
|
||
newPos,
|
||
overPos,
|
||
time = TRANSITION_DURATION,
|
||
speed,
|
||
friction = options.friction;
|
||
|
||
for (var _i = moveTrack.length - 1; _i >= 0; _i--) {
|
||
_backTime = moveTrack[_i][0];
|
||
_timeDiff = Math.abs(_backTime - _backTimeIdeal);
|
||
if (backTime === null || _timeDiff < _timeDiffLast) {
|
||
backTime = _backTime;
|
||
backCoo = moveTrack[_i][1];
|
||
} else if (backTime === _backTimeIdeal || _timeDiff > _timeDiffLast) {
|
||
break;
|
||
}
|
||
_timeDiffLast = _timeDiff;
|
||
}
|
||
|
||
newPos = minMaxLimit(moveElPos, min, max);
|
||
|
||
var cooDiff = backCoo - coo,
|
||
forwardFLAG = cooDiff >= 0,
|
||
timeDiff = endTime - backTime,
|
||
longTouchFLAG = timeDiff > TOUCH_TIMEOUT,
|
||
swipeFLAG = !longTouchFLAG && moveElPos !== startElPos && newPos === moveElPos;
|
||
|
||
if (snap) {
|
||
newPos = minMaxLimit(Math[swipeFLAG ? (forwardFLAG ? 'floor' : 'ceil') : 'round'](moveElPos / snap) * snap, min, max);
|
||
min = max = newPos;
|
||
}
|
||
|
||
if (swipeFLAG && (snap || newPos === moveElPos)) {
|
||
speed = -(cooDiff / timeDiff);
|
||
time *= minMaxLimit(Math.abs(speed), options.timeLow, options.timeHigh);
|
||
virtualPos = Math.round(moveElPos + speed * time / friction);
|
||
|
||
if (!snap) {
|
||
newPos = virtualPos;
|
||
}
|
||
|
||
if (!forwardFLAG && virtualPos > max || forwardFLAG && virtualPos < min) {
|
||
limitPos = forwardFLAG ? min : max;
|
||
overPos = virtualPos - limitPos;
|
||
if (!snap) {
|
||
newPos = limitPos;
|
||
}
|
||
overPos = minMaxLimit(newPos + overPos * .03, limitPos - 50, limitPos + 50);
|
||
time = Math.abs((moveElPos - overPos) / (speed / friction));
|
||
}
|
||
}
|
||
|
||
time *= slowFLAG ? 10 : 1;
|
||
|
||
(options.onEnd || noop).call(el, $.extend(result, {
|
||
moved: result.moved || longTouchFLAG && snap,
|
||
pos: moveElPos,
|
||
newPos: newPos,
|
||
overPos: overPos,
|
||
time: time,
|
||
dir: dir
|
||
}));
|
||
}
|
||
|
||
tail = $.extend(touch(options.$wrap, $.extend({}, options, {
|
||
onStart: onStart,
|
||
onMove: onMove,
|
||
onEnd: onEnd
|
||
})), tail);
|
||
|
||
return tail;
|
||
}
|
||
|
||
function wheel($el, options) {
|
||
var el = $el[0],
|
||
lockFLAG,
|
||
lastDirection,
|
||
lastNow,
|
||
tail = {
|
||
prevent: {}
|
||
};
|
||
|
||
addEvent(el, WHEEL, function (e) {
|
||
var yDelta = e.wheelDeltaY || -1 * e.deltaY || 0,
|
||
xDelta = e.wheelDeltaX || -1 * e.deltaX || 0,
|
||
xWin = Math.abs(xDelta) && !Math.abs(yDelta),
|
||
direction = getDirectionSign(xDelta < 0),
|
||
sameDirection = lastDirection === direction,
|
||
now = $.now(),
|
||
tooFast = now - lastNow < TOUCH_TIMEOUT;
|
||
|
||
lastDirection = direction;
|
||
lastNow = now;
|
||
|
||
if (!xWin || !tail.ok || tail.prevent[direction] && !lockFLAG) {
|
||
return;
|
||
} else {
|
||
stopEvent(e, true);
|
||
if (lockFLAG && sameDirection && tooFast) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (options.shift) {
|
||
lockFLAG = true;
|
||
clearTimeout(tail.t);
|
||
tail.t = setTimeout(function () {
|
||
lockFLAG = false;
|
||
}, SCROLL_LOCK_TIMEOUT);
|
||
}
|
||
|
||
(options.onEnd || noop)(e, options.shift ? direction : xDelta);
|
||
|
||
});
|
||
|
||
return tail;
|
||
}
|
||
|
||
jQuery.Fotorama = function ($fotorama, opts) {
|
||
$HTML = $('html');
|
||
$BODY = $('body');
|
||
|
||
var that = this,
|
||
stamp = $.now(),
|
||
stampClass = _fotoramaClass + stamp,
|
||
fotorama = $fotorama[0],
|
||
data,
|
||
dataFrameCount = 1,
|
||
fotoramaData = $fotorama.data(),
|
||
size,
|
||
|
||
$style = $('<style></style>'),
|
||
|
||
$anchor = $(div(hiddenClass)),
|
||
$wrap = $fotorama.find(cls(wrapClass)),
|
||
$stage = $wrap.find(cls(stageClass)),
|
||
stage = $stage[0],
|
||
|
||
$stageShaft = $fotorama.find(cls(stageShaftClass)),
|
||
$stageFrame = $(),
|
||
$arrPrev = $fotorama.find(cls(arrPrevClass)),
|
||
$arrNext = $fotorama.find(cls(arrNextClass)),
|
||
$arrs = $fotorama.find(cls(arrClass)),
|
||
$navWrap = $fotorama.find(cls(navWrapClass)),
|
||
$nav = $navWrap.find(cls(navClass)),
|
||
$navShaft = $nav.find(cls(navShaftClass)),
|
||
$navFrame,
|
||
$navDotFrame = $(),
|
||
$navThumbFrame = $(),
|
||
|
||
stageShaftData = $stageShaft.data(),
|
||
navShaftData = $navShaft.data(),
|
||
|
||
$thumbBorder = $fotorama.find(cls(thumbBorderClass)),
|
||
$thumbArrLeft = $fotorama.find(cls(thumbArrLeft)),
|
||
$thumbArrRight = $fotorama.find(cls(thumbArrRight)),
|
||
|
||
$fullscreenIcon = $fotorama.find(cls(fullscreenIconClass)),
|
||
fullscreenIcon = $fullscreenIcon[0],
|
||
$videoPlay = $(div(videoPlayClass)),
|
||
$videoClose = $fotorama.find(cls(videoCloseClass)),
|
||
videoClose = $videoClose[0],
|
||
|
||
$spinner = $fotorama.find(cls(fotoramaSpinnerClass)),
|
||
|
||
$videoPlaying,
|
||
|
||
activeIndex = false,
|
||
activeFrame,
|
||
activeIndexes,
|
||
repositionIndex,
|
||
dirtyIndex,
|
||
lastActiveIndex,
|
||
prevIndex,
|
||
nextIndex,
|
||
nextAutoplayIndex,
|
||
startIndex,
|
||
|
||
o_loop,
|
||
o_nav,
|
||
o_navThumbs,
|
||
o_navTop,
|
||
o_allowFullScreen,
|
||
o_nativeFullScreen,
|
||
o_fade,
|
||
o_thumbSide,
|
||
o_thumbSide2,
|
||
o_transitionDuration,
|
||
o_transition,
|
||
o_shadows,
|
||
o_rtl,
|
||
o_keyboard,
|
||
lastOptions = {},
|
||
|
||
measures = {},
|
||
measuresSetFLAG,
|
||
|
||
stageShaftTouchTail = {},
|
||
stageWheelTail = {},
|
||
navShaftTouchTail = {},
|
||
navWheelTail = {},
|
||
|
||
scrollTop,
|
||
scrollLeft,
|
||
|
||
showedFLAG,
|
||
pausedAutoplayFLAG,
|
||
stoppedAutoplayFLAG,
|
||
|
||
toDeactivate = {},
|
||
toDetach = {},
|
||
|
||
measuresStash,
|
||
|
||
touchedFLAG,
|
||
|
||
hoverFLAG,
|
||
|
||
navFrameKey,
|
||
stageLeft = 0,
|
||
|
||
fadeStack = [];
|
||
|
||
$wrap[STAGE_FRAME_KEY] = $('<div class="' + stageFrameClass + '"></div>');
|
||
$wrap[NAV_THUMB_FRAME_KEY] = $($.Fotorama.jst.thumb());
|
||
$wrap[NAV_DOT_FRAME_KEY] = $($.Fotorama.jst.dots());
|
||
|
||
toDeactivate[STAGE_FRAME_KEY] = [];
|
||
toDeactivate[NAV_THUMB_FRAME_KEY] = [];
|
||
toDeactivate[NAV_DOT_FRAME_KEY] = [];
|
||
toDetach[STAGE_FRAME_KEY] = {};
|
||
|
||
$wrap.addClass(CSS3 ? wrapCss3Class : wrapCss2Class);
|
||
|
||
fotoramaData.fotorama = this;
|
||
|
||
/**
|
||
* Search video items in incoming data and transform object for video layout.
|
||
*
|
||
*/
|
||
function checkForVideo() {
|
||
$.each(data, function (i, dataFrame) {
|
||
if (!dataFrame.i) {
|
||
dataFrame.i = dataFrameCount++;
|
||
var video = findVideoId(dataFrame.video, true);
|
||
if (video) {
|
||
var thumbs = {};
|
||
dataFrame.video = video;
|
||
if (!dataFrame.img && !dataFrame.thumb) {
|
||
thumbs = getVideoThumbs(dataFrame, data, that);
|
||
} else {
|
||
dataFrame.thumbsReady = true;
|
||
}
|
||
updateData(data, {img: thumbs.img, thumb: thumbs.thumb}, dataFrame.i, that);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Checks if current media object is YouTube or Vimeo video stream
|
||
* @returns {boolean}
|
||
*/
|
||
function isVideo() {
|
||
return $((that.activeFrame || {}).$stageFrame || {}).hasClass('fotorama-video-container');
|
||
}
|
||
|
||
function allowKey(key) {
|
||
return o_keyboard[key];
|
||
}
|
||
|
||
function setStagePosition() {
|
||
if ($stage !== undefined) {
|
||
|
||
if (opts.navdir == 'vertical') {
|
||
var padding = opts.thumbwidth + opts.thumbmargin;
|
||
|
||
$stage.css('left', padding);
|
||
$arrNext.css('right', padding);
|
||
$fullscreenIcon.css('right', padding);
|
||
$wrap.css('width', $wrap.css('width') + padding);
|
||
$stageShaft.css('max-width', $wrap.width() - padding);
|
||
} else {
|
||
$stage.css('left', '');
|
||
$arrNext.css('right', '');
|
||
$fullscreenIcon.css('right', '');
|
||
$wrap.css('width', $wrap.css('width') + padding);
|
||
$stageShaft.css('max-width', '');
|
||
}
|
||
}
|
||
}
|
||
|
||
function bindGlobalEvents(FLAG) {
|
||
var keydownCommon = 'keydown.' + _fotoramaClass,
|
||
localStamp = _fotoramaClass + stamp,
|
||
keydownLocal = 'keydown.' + localStamp,
|
||
keyupLocal = 'keyup.' + localStamp,
|
||
resizeLocal = 'resize.' + localStamp + ' ' + 'orientationchange.' + localStamp,
|
||
showParams;
|
||
|
||
if (FLAG) {
|
||
$DOCUMENT
|
||
.on(keydownLocal, function (e) {
|
||
var catched,
|
||
index;
|
||
|
||
if ($videoPlaying && e.keyCode === 27) {
|
||
catched = true;
|
||
unloadVideo($videoPlaying, true, true);
|
||
} else if (that.fullScreen || (opts.keyboard && !that.index)) {
|
||
if (e.keyCode === 27) {
|
||
catched = true;
|
||
that.cancelFullScreen();
|
||
} else if ((e.shiftKey && e.keyCode === 32 && allowKey('space')) || (!e.altKey && !e.metaKey && e.keyCode === 37 && allowKey('left')) || (e.keyCode === 38 && allowKey('up') && $(':focus').attr('data-gallery-role'))) {
|
||
that.longPress.progress();
|
||
index = '<';
|
||
} else if ((e.keyCode === 32 && allowKey('space')) || (!e.altKey && !e.metaKey && e.keyCode === 39 && allowKey('right')) || (e.keyCode === 40 && allowKey('down') && $(':focus').attr('data-gallery-role'))) {
|
||
that.longPress.progress();
|
||
index = '>';
|
||
} else if (e.keyCode === 36 && allowKey('home')) {
|
||
that.longPress.progress();
|
||
index = '<<';
|
||
} else if (e.keyCode === 35 && allowKey('end')) {
|
||
that.longPress.progress();
|
||
index = '>>';
|
||
}
|
||
}
|
||
|
||
(catched || index) && stopEvent(e);
|
||
showParams = {index: index, slow: e.altKey, user: true};
|
||
index && (that.longPress.inProgress ?
|
||
that.showWhileLongPress(showParams) :
|
||
that.show(showParams));
|
||
});
|
||
|
||
if (FLAG) {
|
||
$DOCUMENT
|
||
.on(keyupLocal, function (e) {
|
||
if (that.longPress.inProgress) {
|
||
that.showEndLongPress({user: true});
|
||
}
|
||
that.longPress.reset();
|
||
});
|
||
}
|
||
|
||
if (!that.index) {
|
||
$DOCUMENT
|
||
.off(keydownCommon)
|
||
.on(keydownCommon, 'textarea, input, select', function (e) {
|
||
!$BODY.hasClass(_fullscreenClass) && e.stopPropagation();
|
||
});
|
||
}
|
||
|
||
$WINDOW.on(resizeLocal, that.resize);
|
||
} else {
|
||
$DOCUMENT.off(keydownLocal);
|
||
$WINDOW.off(resizeLocal);
|
||
}
|
||
}
|
||
|
||
function appendElements(FLAG) {
|
||
if (FLAG === appendElements.f) return;
|
||
|
||
if (FLAG) {
|
||
$fotorama
|
||
.addClass(_fotoramaClass + ' ' + stampClass)
|
||
.before($anchor)
|
||
.before($style);
|
||
addInstance(that);
|
||
} else {
|
||
$anchor.detach();
|
||
$style.detach();
|
||
$fotorama
|
||
.html(fotoramaData.urtext)
|
||
.removeClass(stampClass);
|
||
|
||
hideInstance(that);
|
||
}
|
||
|
||
bindGlobalEvents(FLAG);
|
||
appendElements.f = FLAG;
|
||
}
|
||
|
||
/**
|
||
* Set and install data from incoming @param {JSON} options or takes data attr from data-"name"=... values.
|
||
*/
|
||
function setData() {
|
||
data = that.data = data || clone(opts.data) || getDataFromHtml($fotorama);
|
||
size = that.size = data.length;
|
||
|
||
ready.ok && opts.shuffle && shuffle(data);
|
||
|
||
checkForVideo();
|
||
|
||
activeIndex = limitIndex(activeIndex);
|
||
|
||
size && appendElements(true);
|
||
}
|
||
|
||
function stageNoMove() {
|
||
var _noMove = size < 2 || $videoPlaying;
|
||
stageShaftTouchTail.noMove = _noMove || o_fade;
|
||
stageShaftTouchTail.noSwipe = _noMove || !opts.swipe;
|
||
|
||
!o_transition && $stageShaft.toggleClass(grabClass, !opts.click && !stageShaftTouchTail.noMove && !stageShaftTouchTail.noSwipe);
|
||
MS_POINTER && $wrap.toggleClass(wrapPanYClass, !stageShaftTouchTail.noSwipe);
|
||
}
|
||
|
||
function setAutoplayInterval(interval) {
|
||
if (interval === true) interval = '';
|
||
opts.autoplay = Math.max(+interval || AUTOPLAY_INTERVAL, o_transitionDuration * 1.5);
|
||
}
|
||
|
||
function updateThumbArrow(opt) {
|
||
if (opt.navarrows && opt.nav === 'thumbs') {
|
||
$thumbArrLeft.show();
|
||
$thumbArrRight.show();
|
||
} else {
|
||
$thumbArrLeft.hide();
|
||
$thumbArrRight.hide();
|
||
}
|
||
|
||
}
|
||
|
||
function getThumbsInSlide($el, opts) {
|
||
return Math.floor($wrap.width() / (opts.thumbwidth + opts.thumbmargin));
|
||
}
|
||
|
||
/**
|
||
* Options on the fly
|
||
* */
|
||
function setOptions() {
|
||
if (!opts.nav || opts.nav === 'dots') {
|
||
opts.navdir = 'horizontal'
|
||
}
|
||
|
||
that.options = opts = optionsToLowerCase(opts);
|
||
thumbsPerSlide = getThumbsInSlide($wrap, opts);
|
||
|
||
o_fade = (opts.transition === 'crossfade' || opts.transition === 'dissolve');
|
||
|
||
o_loop = opts.loop && (size > 2 || (o_fade && (!o_transition || o_transition !== 'slide')));
|
||
|
||
o_transitionDuration = +opts.transitionduration || TRANSITION_DURATION;
|
||
|
||
o_rtl = opts.direction === 'rtl';
|
||
|
||
o_keyboard = $.extend({}, opts.keyboard && KEYBOARD_OPTIONS, opts.keyboard);
|
||
updateThumbArrow(opts);
|
||
var classes = {add: [], remove: []};
|
||
|
||
function addOrRemoveClass(FLAG, value) {
|
||
classes[FLAG ? 'add' : 'remove'].push(value);
|
||
}
|
||
|
||
if (size > 1) {
|
||
o_nav = opts.nav;
|
||
o_navTop = opts.navposition === 'top';
|
||
classes.remove.push(selectClass);
|
||
|
||
$arrs.toggle(!!opts.arrows);
|
||
} else {
|
||
o_nav = false;
|
||
$arrs.hide();
|
||
}
|
||
|
||
arrsUpdate();
|
||
stageWheelUpdate();
|
||
thumbArrUpdate();
|
||
if (opts.autoplay) setAutoplayInterval(opts.autoplay);
|
||
|
||
o_thumbSide = numberFromMeasure(opts.thumbwidth) || THUMB_SIZE;
|
||
o_thumbSide2 = numberFromMeasure(opts.thumbheight) || THUMB_SIZE;
|
||
|
||
stageWheelTail.ok = navWheelTail.ok = opts.trackpad && !SLOW;
|
||
|
||
stageNoMove();
|
||
|
||
extendMeasures(opts, [measures]);
|
||
|
||
o_navThumbs = o_nav === 'thumbs';
|
||
|
||
if ($navWrap.filter(':hidden') && !!o_nav) {
|
||
$navWrap.show();
|
||
}
|
||
if (o_navThumbs) {
|
||
frameDraw(size, 'navThumb');
|
||
|
||
$navFrame = $navThumbFrame;
|
||
navFrameKey = NAV_THUMB_FRAME_KEY;
|
||
|
||
setStyle($style, $.Fotorama.jst.style({
|
||
w: o_thumbSide,
|
||
h: o_thumbSide2,
|
||
b: opts.thumbborderwidth,
|
||
m: opts.thumbmargin,
|
||
s: stamp,
|
||
q: !COMPAT
|
||
}));
|
||
|
||
$nav
|
||
.addClass(navThumbsClass)
|
||
.removeClass(navDotsClass);
|
||
} else if (o_nav === 'dots') {
|
||
frameDraw(size, 'navDot');
|
||
|
||
$navFrame = $navDotFrame;
|
||
navFrameKey = NAV_DOT_FRAME_KEY;
|
||
|
||
$nav
|
||
.addClass(navDotsClass)
|
||
.removeClass(navThumbsClass);
|
||
} else {
|
||
$navWrap.hide();
|
||
o_nav = false;
|
||
$nav.removeClass(navThumbsClass + ' ' + navDotsClass);
|
||
}
|
||
|
||
if (o_nav) {
|
||
if (o_navTop) {
|
||
$navWrap.insertBefore($stage);
|
||
} else {
|
||
$navWrap.insertAfter($stage);
|
||
}
|
||
frameAppend.nav = false;
|
||
|
||
frameAppend($navFrame, $navShaft, 'nav');
|
||
}
|
||
|
||
o_allowFullScreen = opts.allowfullscreen;
|
||
|
||
if (o_allowFullScreen) {
|
||
$fullscreenIcon.prependTo($stage);
|
||
o_nativeFullScreen = FULLSCREEN && o_allowFullScreen === 'native';
|
||
} else {
|
||
$fullscreenIcon.detach();
|
||
o_nativeFullScreen = false;
|
||
}
|
||
|
||
addOrRemoveClass(o_fade, wrapFadeClass);
|
||
addOrRemoveClass(!o_fade, wrapSlideClass);
|
||
addOrRemoveClass(!opts.captions, wrapNoCaptionsClass);
|
||
addOrRemoveClass(o_rtl, wrapRtlClass);
|
||
addOrRemoveClass(opts.arrows, wrapToggleArrowsClass);
|
||
|
||
o_shadows = opts.shadows && !SLOW;
|
||
addOrRemoveClass(!o_shadows, wrapNoShadowsClass);
|
||
|
||
$wrap
|
||
.addClass(classes.add.join(' '))
|
||
.removeClass(classes.remove.join(' '));
|
||
|
||
lastOptions = $.extend({}, opts);
|
||
setStagePosition();
|
||
}
|
||
|
||
function normalizeIndex(index) {
|
||
return index < 0 ? (size + (index % size)) % size : index >= size ? index % size : index;
|
||
}
|
||
|
||
function limitIndex(index) {
|
||
return minMaxLimit(index, 0, size - 1);
|
||
}
|
||
|
||
function edgeIndex(index) {
|
||
return o_loop ? normalizeIndex(index) : limitIndex(index);
|
||
}
|
||
|
||
function getPrevIndex(index) {
|
||
return index > 0 || o_loop ? index - 1 : false;
|
||
}
|
||
|
||
function getNextIndex(index) {
|
||
return index < size - 1 || o_loop ? index + 1 : false;
|
||
}
|
||
|
||
function setStageShaftMinmaxAndSnap() {
|
||
stageShaftTouchTail.min = o_loop ? -Infinity : -getPosByIndex(size - 1, measures.w, opts.margin, repositionIndex);
|
||
stageShaftTouchTail.max = o_loop ? Infinity : -getPosByIndex(0, measures.w, opts.margin, repositionIndex);
|
||
stageShaftTouchTail.snap = measures.w + opts.margin;
|
||
}
|
||
|
||
function setNavShaftMinMax() {
|
||
|
||
var isVerticalDir = (opts.navdir === 'vertical');
|
||
var param = isVerticalDir ? $navShaft.height() : $navShaft.width();
|
||
var mainParam = isVerticalDir ? measures.h : measures.nw;
|
||
navShaftTouchTail.min = Math.min(0, mainParam - param);
|
||
navShaftTouchTail.max = 0;
|
||
navShaftTouchTail.direction = opts.navdir;
|
||
$navShaft.toggleClass(grabClass, !(navShaftTouchTail.noMove = navShaftTouchTail.min === navShaftTouchTail.max));
|
||
}
|
||
|
||
function eachIndex(indexes, type, fn) {
|
||
if (typeof indexes === 'number') {
|
||
indexes = new Array(indexes);
|
||
var rangeFLAG = true;
|
||
}
|
||
return $.each(indexes, function (i, index) {
|
||
if (rangeFLAG) index = i;
|
||
if (typeof index === 'number') {
|
||
var dataFrame = data[normalizeIndex(index)];
|
||
|
||
if (dataFrame) {
|
||
var key = '$' + type + 'Frame',
|
||
$frame = dataFrame[key];
|
||
|
||
fn.call(this, i, index, dataFrame, $frame, key, $frame && $frame.data());
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
function setMeasures(width, height, ratio, index) {
|
||
if (!measuresSetFLAG || (measuresSetFLAG === '*' && index === startIndex)) {
|
||
|
||
width = measureIsValid(opts.width) || measureIsValid(width) || WIDTH;
|
||
height = measureIsValid(opts.height) || measureIsValid(height) || HEIGHT;
|
||
that.resize({
|
||
width: width,
|
||
ratio: opts.ratio || ratio || width / height
|
||
}, 0, index !== startIndex && '*');
|
||
}
|
||
}
|
||
|
||
function loadImg(indexes, type, specialMeasures, again) {
|
||
|
||
eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) {
|
||
|
||
if (!$frame) return;
|
||
|
||
var fullFLAG = that.fullScreen && !frameData.$full && type === 'stage';
|
||
|
||
if (frameData.$img && !again && !fullFLAG) return;
|
||
|
||
var img = new Image(),
|
||
$img = $(img),
|
||
imgData = $img.data();
|
||
|
||
frameData[fullFLAG ? '$full' : '$img'] = $img;
|
||
|
||
var srcKey = type === 'stage' ? (fullFLAG ? 'full' : 'img') : 'thumb',
|
||
src = dataFrame[srcKey],
|
||
dummy = fullFLAG ? dataFrame['img'] : dataFrame[type === 'stage' ? 'thumb' : 'img'];
|
||
|
||
if (type === 'navThumb') $frame = frameData.$wrap;
|
||
|
||
function triggerTriggerEvent(event) {
|
||
var _index = normalizeIndex(index);
|
||
triggerEvent(event, {
|
||
index: _index,
|
||
src: src,
|
||
frame: data[_index]
|
||
});
|
||
}
|
||
|
||
function error() {
|
||
$img.remove();
|
||
|
||
$.Fotorama.cache[src] = 'error';
|
||
|
||
if ((!dataFrame.html || type !== 'stage') && dummy && dummy !== src) {
|
||
dataFrame[srcKey] = src = dummy;
|
||
frameData.$full = null;
|
||
loadImg([index], type, specialMeasures, true);
|
||
} else {
|
||
if (src && !dataFrame.html && !fullFLAG) {
|
||
$frame
|
||
.trigger('f:error')
|
||
.removeClass(loadingClass)
|
||
.addClass(errorClass);
|
||
|
||
triggerTriggerEvent('error');
|
||
} else if (type === 'stage') {
|
||
$frame
|
||
.trigger('f:load')
|
||
.removeClass(loadingClass + ' ' + errorClass)
|
||
.addClass(loadedClass);
|
||
|
||
triggerTriggerEvent('load');
|
||
setMeasures();
|
||
}
|
||
|
||
frameData.state = 'error';
|
||
|
||
if (size > 1 && data[index] === dataFrame && !dataFrame.html && !dataFrame.deleted && !dataFrame.video && !fullFLAG) {
|
||
dataFrame.deleted = true;
|
||
that.splice(index, 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
function loaded() {
|
||
$.Fotorama.measures[src] = imgData.measures = $.Fotorama.measures[src] || {
|
||
width: img.width,
|
||
height: img.height,
|
||
ratio: img.width / img.height
|
||
};
|
||
|
||
setMeasures(imgData.measures.width, imgData.measures.height, imgData.measures.ratio, index);
|
||
|
||
$img
|
||
.off('load error')
|
||
.addClass('' + (fullFLAG ? imgFullClass: imgClass))
|
||
.attr('aria-hidden', 'false')
|
||
.prependTo($frame);
|
||
|
||
if ($frame.hasClass(stageFrameClass) && !$frame.hasClass(videoContainerClass)) {
|
||
$frame.attr("href", $img.attr("src"));
|
||
}
|
||
|
||
fit($img, (
|
||
$.isFunction(specialMeasures) ? specialMeasures() : specialMeasures) || measures);
|
||
|
||
$.Fotorama.cache[src] = frameData.state = 'loaded';
|
||
|
||
setTimeout(function () {
|
||
$frame
|
||
.trigger('f:load')
|
||
.removeClass(loadingClass + ' ' + errorClass)
|
||
.addClass(loadedClass + ' ' + (fullFLAG ? loadedFullClass : loadedImgClass));
|
||
|
||
if (type === 'stage') {
|
||
triggerTriggerEvent('load');
|
||
} else if (dataFrame.thumbratio === AUTO || !dataFrame.thumbratio && opts.thumbratio === AUTO) {
|
||
// danger! reflow for all thumbnails
|
||
dataFrame.thumbratio = imgData.measures.ratio;
|
||
reset();
|
||
}
|
||
}, 0);
|
||
}
|
||
|
||
if (!src) {
|
||
error();
|
||
return;
|
||
}
|
||
|
||
function waitAndLoad() {
|
||
var _i = 10;
|
||
waitFor(function () {
|
||
return !touchedFLAG || !_i-- && !SLOW;
|
||
}, function () {
|
||
loaded();
|
||
});
|
||
}
|
||
|
||
if (!$.Fotorama.cache[src]) {
|
||
$.Fotorama.cache[src] = '*';
|
||
|
||
$img
|
||
.on('load', waitAndLoad)
|
||
.on('error', error);
|
||
} else {
|
||
(function justWait() {
|
||
if ($.Fotorama.cache[src] === 'error') {
|
||
error();
|
||
} else if ($.Fotorama.cache[src] === 'loaded') {
|
||
setTimeout(waitAndLoad, 0);
|
||
} else {
|
||
setTimeout(justWait, 100);
|
||
}
|
||
})();
|
||
}
|
||
|
||
frameData.state = '';
|
||
img.src = src;
|
||
|
||
if (frameData.data.caption) {
|
||
img.alt = frameData.data.caption || "";
|
||
}
|
||
|
||
if (frameData.data.full) {
|
||
$(img).data('original', frameData.data.full);
|
||
}
|
||
|
||
if (UTIL.isExpectedCaption(dataFrame, opts.showcaption)) {
|
||
$(img).attr('aria-labelledby', dataFrame.labelledby);
|
||
}
|
||
});
|
||
}
|
||
|
||
function updateFotoramaState() {
|
||
var $frame = activeFrame[STAGE_FRAME_KEY];
|
||
|
||
if ($frame && !$frame.data().state) {
|
||
$spinner.addClass(spinnerShowClass);
|
||
$frame.on('f:load f:error', function () {
|
||
$frame.off('f:load f:error');
|
||
$spinner.removeClass(spinnerShowClass);
|
||
});
|
||
}
|
||
}
|
||
|
||
function addNavFrameEvents(frame) {
|
||
addEnterUp(frame, onNavFrameClick);
|
||
addFocus(frame, function () {
|
||
|
||
setTimeout(function () {
|
||
lockScroll($nav);
|
||
}, 0);
|
||
slideNavShaft({time: o_transitionDuration, guessIndex: $(this).data().eq, minMax: navShaftTouchTail});
|
||
});
|
||
}
|
||
|
||
function frameDraw(indexes, type) {
|
||
eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) {
|
||
if ($frame) return;
|
||
|
||
$frame = dataFrame[key] = $wrap[key].clone();
|
||
frameData = $frame.data();
|
||
frameData.data = dataFrame;
|
||
var frame = $frame[0],
|
||
labelledbyValue = "labelledby" + $.now();
|
||
|
||
if (type === 'stage') {
|
||
|
||
if (dataFrame.html) {
|
||
$('<div class="' + htmlClass + '"></div>')
|
||
.append(
|
||
dataFrame._html ? $(dataFrame.html)
|
||
.removeAttr('id')
|
||
.html(dataFrame._html) // Because of IE
|
||
: dataFrame.html
|
||
)
|
||
.appendTo($frame);
|
||
}
|
||
|
||
if (dataFrame.id) {
|
||
labelledbyValue = dataFrame.id || labelledbyValue;
|
||
}
|
||
dataFrame.labelledby = labelledbyValue;
|
||
|
||
if (UTIL.isExpectedCaption(dataFrame, opts.showcaption)) {
|
||
$($.Fotorama.jst.frameCaption({
|
||
caption: dataFrame.caption,
|
||
labelledby: labelledbyValue
|
||
})).appendTo($frame);
|
||
}
|
||
|
||
dataFrame.video && $frame
|
||
.addClass(stageFrameVideoClass)
|
||
.append($videoPlay.clone());
|
||
|
||
// This solves tabbing problems
|
||
addFocus(frame, function (e) {
|
||
setTimeout(function () {
|
||
lockScroll($stage);
|
||
}, 0);
|
||
clickToShow({index: frameData.eq, user: true}, e);
|
||
});
|
||
|
||
$stageFrame = $stageFrame.add($frame);
|
||
} else if (type === 'navDot') {
|
||
addNavFrameEvents(frame);
|
||
$navDotFrame = $navDotFrame.add($frame);
|
||
} else if (type === 'navThumb') {
|
||
addNavFrameEvents(frame);
|
||
frameData.$wrap = $frame.children(':first');
|
||
|
||
$navThumbFrame = $navThumbFrame.add($frame);
|
||
if (dataFrame.video) {
|
||
frameData.$wrap.append($videoPlay.clone());
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
function callFit($img, measuresToFit) {
|
||
return $img && $img.length && fit($img, measuresToFit);
|
||
}
|
||
|
||
function stageFramePosition(indexes) {
|
||
eachIndex(indexes, 'stage', function (i, index, dataFrame, $frame, key, frameData) {
|
||
if (!$frame) return;
|
||
|
||
var normalizedIndex = normalizeIndex(index);
|
||
frameData.eq = normalizedIndex;
|
||
|
||
toDetach[STAGE_FRAME_KEY][normalizedIndex] = $frame.css($.extend({left: o_fade ? 0 : getPosByIndex(index, measures.w, opts.margin, repositionIndex)}, o_fade && getDuration(0)));
|
||
|
||
if (isDetached($frame[0])) {
|
||
$frame.appendTo($stageShaft);
|
||
unloadVideo(dataFrame.$video);
|
||
}
|
||
|
||
callFit(frameData.$img, measures);
|
||
callFit(frameData.$full, measures);
|
||
|
||
if ($frame.hasClass(stageFrameClass) && !($frame.attr('aria-hidden') === "false" && $frame.hasClass(activeClass))) {
|
||
$frame.attr('aria-hidden', 'true');
|
||
}
|
||
});
|
||
}
|
||
|
||
function thumbsDraw(pos, loadFLAG) {
|
||
var leftLimit,
|
||
rightLimit,
|
||
exceedLimit;
|
||
|
||
|
||
if (o_nav !== 'thumbs' || isNaN(pos)) return;
|
||
|
||
leftLimit = -pos;
|
||
rightLimit = -pos + measures.nw;
|
||
|
||
if (opts.navdir === 'vertical') {
|
||
pos = pos - opts.thumbheight;
|
||
rightLimit = -pos + measures.h;
|
||
}
|
||
|
||
$navThumbFrame.each(function () {
|
||
var $this = $(this),
|
||
thisData = $this.data(),
|
||
eq = thisData.eq,
|
||
getSpecialMeasures = function () {
|
||
return {
|
||
h: o_thumbSide2,
|
||
w: thisData.w
|
||
}
|
||
},
|
||
specialMeasures = getSpecialMeasures(),
|
||
exceedLimit = opts.navdir === 'vertical' ?
|
||
thisData.t > rightLimit : thisData.l > rightLimit;
|
||
specialMeasures.w = thisData.w;
|
||
|
||
if ((opts.navdir !== 'vertical' && thisData.l + thisData.w < leftLimit)
|
||
|| exceedLimit
|
||
|| callFit(thisData.$img, specialMeasures)) return;
|
||
|
||
loadFLAG && loadImg([eq], 'navThumb', getSpecialMeasures);
|
||
});
|
||
}
|
||
|
||
function frameAppend($frames, $shaft, type) {
|
||
if (!frameAppend[type]) {
|
||
|
||
var thumbsFLAG = type === 'nav' && o_navThumbs,
|
||
left = 0,
|
||
top = 0;
|
||
|
||
$shaft.append(
|
||
$frames
|
||
.filter(function () {
|
||
var actual,
|
||
$this = $(this),
|
||
frameData = $this.data();
|
||
for (var _i = 0, _l = data.length; _i < _l; _i++) {
|
||
if (frameData.data === data[_i]) {
|
||
actual = true;
|
||
frameData.eq = _i;
|
||
break;
|
||
}
|
||
}
|
||
return actual || $this.remove() && false;
|
||
})
|
||
.sort(function (a, b) {
|
||
return $(a).data().eq - $(b).data().eq;
|
||
})
|
||
.each(function () {
|
||
var $this = $(this),
|
||
frameData = $this.data();
|
||
UTIL.setThumbAttr($this, frameData.data.caption, "aria-label");
|
||
})
|
||
.each(function () {
|
||
|
||
if (!thumbsFLAG) return;
|
||
|
||
var $this = $(this),
|
||
frameData = $this.data(),
|
||
thumbwidth = Math.round(o_thumbSide2 * frameData.data.thumbratio) || o_thumbSide,
|
||
thumbheight = Math.round(o_thumbSide / frameData.data.thumbratio) || o_thumbSide2;
|
||
frameData.t = top;
|
||
frameData.h = thumbheight;
|
||
frameData.l = left;
|
||
frameData.w = thumbwidth;
|
||
|
||
$this.css({width: thumbwidth});
|
||
|
||
top += thumbheight + opts.thumbmargin;
|
||
left += thumbwidth + opts.thumbmargin;
|
||
})
|
||
);
|
||
|
||
frameAppend[type] = true;
|
||
}
|
||
}
|
||
|
||
function getDirection(x) {
|
||
return x - stageLeft > measures.w / 3;
|
||
}
|
||
|
||
function disableDirrection(i) {
|
||
return !o_loop && (!(activeIndex + i) || !(activeIndex - size + i)) && !$videoPlaying;
|
||
}
|
||
|
||
function arrsUpdate() {
|
||
var disablePrev = disableDirrection(0),
|
||
disableNext = disableDirrection(1);
|
||
$arrPrev
|
||
.toggleClass(arrDisabledClass, disablePrev)
|
||
.attr(disableAttr(disablePrev, false));
|
||
$arrNext
|
||
.toggleClass(arrDisabledClass, disableNext)
|
||
.attr(disableAttr(disableNext, false));
|
||
}
|
||
|
||
function thumbArrUpdate() {
|
||
var isLeftDisable = false,
|
||
isRightDisable = false;
|
||
if (opts.navtype === 'thumbs' && !opts.loop) {
|
||
(activeIndex == 0) ? isLeftDisable = true : isLeftDisable = false;
|
||
(activeIndex == opts.data.length - 1) ? isRightDisable = true : isRightDisable = false;
|
||
}
|
||
if (opts.navtype === 'slides') {
|
||
var pos = readPosition($navShaft, opts.navdir);
|
||
pos >= navShaftTouchTail.max ? isLeftDisable = true : isLeftDisable = false;
|
||
pos <= Math.round(navShaftTouchTail.min) ? isRightDisable = true : isRightDisable = false;
|
||
}
|
||
$thumbArrLeft
|
||
.toggleClass(arrDisabledClass, isLeftDisable)
|
||
.attr(disableAttr(isLeftDisable, true));
|
||
$thumbArrRight
|
||
.toggleClass(arrDisabledClass, isRightDisable)
|
||
.attr(disableAttr(isRightDisable, true));
|
||
}
|
||
|
||
function stageWheelUpdate() {
|
||
if (stageWheelTail.ok) {
|
||
stageWheelTail.prevent = {'<': disableDirrection(0), '>': disableDirrection(1)};
|
||
}
|
||
}
|
||
|
||
function getNavFrameBounds($navFrame) {
|
||
var navFrameData = $navFrame.data(),
|
||
left,
|
||
top,
|
||
width,
|
||
height;
|
||
|
||
if (o_navThumbs) {
|
||
left = navFrameData.l;
|
||
top = navFrameData.t;
|
||
width = navFrameData.w;
|
||
height = navFrameData.h;
|
||
} else {
|
||
left = $navFrame.position().left;
|
||
width = $navFrame.width();
|
||
}
|
||
|
||
var horizontalBounds = {
|
||
c: left + width / 2,
|
||
min: -left + opts.thumbmargin * 10,
|
||
max: -left + measures.w - width - opts.thumbmargin * 10
|
||
};
|
||
|
||
var verticalBounds = {
|
||
c: top + height / 2,
|
||
min: -top + opts.thumbmargin * 10,
|
||
max: -top + measures.h - height - opts.thumbmargin * 10
|
||
};
|
||
|
||
return opts.navdir === 'vertical' ? verticalBounds : horizontalBounds;
|
||
}
|
||
|
||
function slideThumbBorder(time) {
|
||
var navFrameData = activeFrame[navFrameKey].data();
|
||
slide($thumbBorder, {
|
||
time: time * 1.2,
|
||
pos: (opts.navdir === 'vertical' ? navFrameData.t : navFrameData.l),
|
||
width: navFrameData.w,
|
||
height: navFrameData.h,
|
||
direction: opts.navdir
|
||
});
|
||
}
|
||
|
||
function slideNavShaft(options) {
|
||
var $guessNavFrame = data[options.guessIndex][navFrameKey],
|
||
typeOfAnimation = opts.navtype;
|
||
|
||
var overflowFLAG,
|
||
time,
|
||
minMax,
|
||
boundTop,
|
||
boundLeft,
|
||
l,
|
||
pos,
|
||
x;
|
||
|
||
if ($guessNavFrame) {
|
||
if (typeOfAnimation === 'thumbs') {
|
||
overflowFLAG = navShaftTouchTail.min !== navShaftTouchTail.max;
|
||
minMax = options.minMax || overflowFLAG && getNavFrameBounds(activeFrame[navFrameKey]);
|
||
boundTop = overflowFLAG && (options.keep && slideNavShaft.t ? slideNavShaft.l : minMaxLimit((options.coo || measures.nw / 2) - getNavFrameBounds($guessNavFrame).c, minMax.min, minMax.max));
|
||
boundLeft = overflowFLAG && (options.keep && slideNavShaft.l ? slideNavShaft.l : minMaxLimit((options.coo || measures.nw / 2) - getNavFrameBounds($guessNavFrame).c, minMax.min, minMax.max));
|
||
l = (opts.navdir === 'vertical' ? boundTop : boundLeft);
|
||
pos = overflowFLAG && minMaxLimit(l, navShaftTouchTail.min, navShaftTouchTail.max) || 0;
|
||
time = options.time * 1.1;
|
||
slide($navShaft, {
|
||
time: time,
|
||
pos: pos,
|
||
direction: opts.navdir,
|
||
onEnd: function () {
|
||
thumbsDraw(pos, true);
|
||
thumbArrUpdate();
|
||
}
|
||
});
|
||
|
||
setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max, opts.navdir));
|
||
slideNavShaft.l = l;
|
||
} else {
|
||
x = readPosition($navShaft, opts.navdir);
|
||
time = options.time * 1.11;
|
||
|
||
pos = validateSlidePos(opts, navShaftTouchTail, options.guessIndex, x, $guessNavFrame, $navWrap, opts.navdir);
|
||
|
||
slide($navShaft, {
|
||
time: time,
|
||
pos: pos,
|
||
direction: opts.navdir,
|
||
onEnd: function () {
|
||
thumbsDraw(pos, true);
|
||
thumbArrUpdate();
|
||
}
|
||
});
|
||
setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max, opts.navdir));
|
||
}
|
||
}
|
||
}
|
||
|
||
function navUpdate() {
|
||
deactivateFrames(navFrameKey);
|
||
toDeactivate[navFrameKey].push(activeFrame[navFrameKey].addClass(activeClass).attr('data-active', true));
|
||
}
|
||
|
||
function deactivateFrames(key) {
|
||
var _toDeactivate = toDeactivate[key];
|
||
|
||
while (_toDeactivate.length) {
|
||
_toDeactivate.shift().removeClass(activeClass).attr('data-active', false);
|
||
}
|
||
}
|
||
|
||
function detachFrames(key) {
|
||
var _toDetach = toDetach[key];
|
||
|
||
$.each(activeIndexes, function (i, index) {
|
||
delete _toDetach[normalizeIndex(index)];
|
||
});
|
||
|
||
$.each(_toDetach, function (index, $frame) {
|
||
delete _toDetach[index];
|
||
$frame.detach();
|
||
});
|
||
}
|
||
|
||
function stageShaftReposition(skipOnEnd) {
|
||
|
||
repositionIndex = dirtyIndex = activeIndex;
|
||
|
||
var $frame = activeFrame[STAGE_FRAME_KEY];
|
||
|
||
if ($frame) {
|
||
deactivateFrames(STAGE_FRAME_KEY);
|
||
toDeactivate[STAGE_FRAME_KEY].push($frame.addClass(activeClass).attr('data-active', true));
|
||
|
||
if ($frame.hasClass(stageFrameClass)) {
|
||
$frame.attr('aria-hidden', 'false');
|
||
}
|
||
|
||
skipOnEnd || that.showStage.onEnd(true);
|
||
stop($stageShaft, 0, true);
|
||
|
||
detachFrames(STAGE_FRAME_KEY);
|
||
stageFramePosition(activeIndexes);
|
||
setStageShaftMinmaxAndSnap();
|
||
setNavShaftMinMax();
|
||
addEnterUp($stageShaft[0], function () {
|
||
if (!$fotorama.hasClass(fullscreenClass)) {
|
||
that.requestFullScreen();
|
||
$fullscreenIcon.focus();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
function extendMeasures(options, measuresArray) {
|
||
if (!options) return;
|
||
|
||
$.each(measuresArray, function (i, measures) {
|
||
if (!measures) return;
|
||
|
||
$.extend(measures, {
|
||
width: options.width || measures.width,
|
||
height: options.height,
|
||
minwidth: options.minwidth,
|
||
maxwidth: options.maxwidth,
|
||
minheight: options.minheight,
|
||
maxheight: options.maxheight,
|
||
ratio: getRatio(options.ratio)
|
||
})
|
||
});
|
||
}
|
||
|
||
function triggerEvent(event, extra) {
|
||
$fotorama.trigger(_fotoramaClass + ':' + event, [that, extra]);
|
||
}
|
||
|
||
function onTouchStart() {
|
||
clearTimeout(onTouchEnd.t);
|
||
touchedFLAG = 1;
|
||
|
||
if (opts.stopautoplayontouch) {
|
||
that.stopAutoplay();
|
||
} else {
|
||
pausedAutoplayFLAG = true;
|
||
}
|
||
}
|
||
|
||
function onTouchEnd() {
|
||
if (!touchedFLAG) return;
|
||
if (!opts.stopautoplayontouch) {
|
||
releaseAutoplay();
|
||
changeAutoplay();
|
||
}
|
||
|
||
onTouchEnd.t = setTimeout(function () {
|
||
touchedFLAG = 0;
|
||
}, TRANSITION_DURATION + TOUCH_TIMEOUT);
|
||
}
|
||
|
||
function releaseAutoplay() {
|
||
pausedAutoplayFLAG = !!($videoPlaying || stoppedAutoplayFLAG);
|
||
}
|
||
|
||
function changeAutoplay() {
|
||
|
||
clearTimeout(changeAutoplay.t);
|
||
waitFor.stop(changeAutoplay.w);
|
||
|
||
if (!opts.autoplay || pausedAutoplayFLAG) {
|
||
if (that.autoplay) {
|
||
that.autoplay = false;
|
||
triggerEvent('stopautoplay');
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
if (!that.autoplay) {
|
||
that.autoplay = true;
|
||
triggerEvent('startautoplay');
|
||
}
|
||
|
||
var _activeIndex = activeIndex;
|
||
|
||
|
||
var frameData = activeFrame[STAGE_FRAME_KEY].data();
|
||
changeAutoplay.w = waitFor(function () {
|
||
return frameData.state || _activeIndex !== activeIndex;
|
||
}, function () {
|
||
changeAutoplay.t = setTimeout(function () {
|
||
|
||
if (pausedAutoplayFLAG || _activeIndex !== activeIndex) return;
|
||
|
||
var _nextAutoplayIndex = nextAutoplayIndex,
|
||
nextFrameData = data[_nextAutoplayIndex][STAGE_FRAME_KEY].data();
|
||
|
||
changeAutoplay.w = waitFor(function () {
|
||
|
||
return nextFrameData.state || _nextAutoplayIndex !== nextAutoplayIndex;
|
||
}, function () {
|
||
if (pausedAutoplayFLAG || _nextAutoplayIndex !== nextAutoplayIndex) return;
|
||
that.show(o_loop ? getDirectionSign(!o_rtl) : nextAutoplayIndex);
|
||
});
|
||
}, opts.autoplay);
|
||
});
|
||
|
||
}
|
||
|
||
that.startAutoplay = function (interval) {
|
||
if (that.autoplay) return this;
|
||
pausedAutoplayFLAG = stoppedAutoplayFLAG = false;
|
||
setAutoplayInterval(interval || opts.autoplay);
|
||
changeAutoplay();
|
||
|
||
return this;
|
||
};
|
||
|
||
that.stopAutoplay = function () {
|
||
if (that.autoplay) {
|
||
pausedAutoplayFLAG = stoppedAutoplayFLAG = true;
|
||
changeAutoplay();
|
||
}
|
||
return this;
|
||
};
|
||
|
||
that.showSlide = function (slideDir) {
|
||
var currentPosition = readPosition($navShaft, opts.navdir),
|
||
pos,
|
||
time = 500 * 1.1,
|
||
size = opts.navdir === 'horizontal' ? opts.thumbwidth : opts.thumbheight,
|
||
onEnd = function () {
|
||
thumbArrUpdate();
|
||
};
|
||
if (slideDir === 'next') {
|
||
pos = currentPosition - (size + opts.margin) * thumbsPerSlide;
|
||
}
|
||
if (slideDir === 'prev') {
|
||
pos = currentPosition + (size + opts.margin) * thumbsPerSlide;
|
||
}
|
||
pos = validateRestrictions(pos, navShaftTouchTail);
|
||
thumbsDraw(pos, true);
|
||
slide($navShaft, {
|
||
time: time,
|
||
pos: pos,
|
||
direction: opts.navdir,
|
||
onEnd: onEnd
|
||
});
|
||
};
|
||
|
||
that.showWhileLongPress = function (options) {
|
||
if (that.longPress.singlePressInProgress) {
|
||
return;
|
||
}
|
||
|
||
var index = calcActiveIndex(options);
|
||
calcGlobalIndexes(index);
|
||
var time = calcTime(options) / 50;
|
||
var _activeFrame = activeFrame;
|
||
that.activeFrame = activeFrame = data[activeIndex];
|
||
var silent = _activeFrame === activeFrame && !options.user;
|
||
|
||
that.showNav(silent, options, time);
|
||
|
||
return this;
|
||
};
|
||
|
||
that.showEndLongPress = function (options) {
|
||
if (that.longPress.singlePressInProgress) {
|
||
return;
|
||
}
|
||
|
||
var index = calcActiveIndex(options);
|
||
calcGlobalIndexes(index);
|
||
var time = calcTime(options) / 50;
|
||
var _activeFrame = activeFrame;
|
||
that.activeFrame = activeFrame = data[activeIndex];
|
||
|
||
var silent = _activeFrame === activeFrame && !options.user;
|
||
|
||
that.showStage(silent, options, time);
|
||
|
||
showedFLAG = typeof lastActiveIndex !== 'undefined' && lastActiveIndex !== activeIndex;
|
||
lastActiveIndex = activeIndex;
|
||
return this;
|
||
};
|
||
|
||
function calcActiveIndex (options) {
|
||
var index;
|
||
|
||
if (typeof options !== 'object') {
|
||
index = options;
|
||
options = {};
|
||
} else {
|
||
index = options.index;
|
||
}
|
||
|
||
index = index === '>' ? dirtyIndex + 1 : index === '<' ? dirtyIndex - 1 : index === '<<' ? 0 : index === '>>' ? size - 1 : index;
|
||
index = isNaN(index) ? undefined : index;
|
||
index = typeof index === 'undefined' ? activeIndex || 0 : index;
|
||
|
||
return index;
|
||
}
|
||
|
||
function calcGlobalIndexes (index) {
|
||
that.activeIndex = activeIndex = edgeIndex(index);
|
||
prevIndex = getPrevIndex(activeIndex);
|
||
nextIndex = getNextIndex(activeIndex);
|
||
nextAutoplayIndex = normalizeIndex(activeIndex + (o_rtl ? -1 : 1));
|
||
activeIndexes = [activeIndex, prevIndex, nextIndex];
|
||
|
||
dirtyIndex = o_loop ? index : activeIndex;
|
||
}
|
||
|
||
function calcTime (options) {
|
||
var diffIndex = Math.abs(lastActiveIndex - dirtyIndex),
|
||
time = getNumber(options.time, function () {
|
||
return Math.min(o_transitionDuration * (1 + (diffIndex - 1) / 12), o_transitionDuration * 2);
|
||
});
|
||
|
||
if (options.slow) {
|
||
time *= 10;
|
||
}
|
||
|
||
return time;
|
||
}
|
||
|
||
that.showStage = function (silent, options, time, e) {
|
||
if (e !== undefined && e.target.tagName == 'IFRAME') {
|
||
return;
|
||
}
|
||
unloadVideo($videoPlaying, activeFrame.i !== data[normalizeIndex(repositionIndex)].i);
|
||
frameDraw(activeIndexes, 'stage');
|
||
stageFramePosition(SLOW ? [dirtyIndex] : [dirtyIndex, getPrevIndex(dirtyIndex), getNextIndex(dirtyIndex)]);
|
||
updateTouchTails('go', true);
|
||
|
||
silent || triggerEvent('show', {
|
||
user: options.user,
|
||
time: time
|
||
});
|
||
|
||
pausedAutoplayFLAG = true;
|
||
|
||
var overPos = options.overPos;
|
||
var onEnd = that.showStage.onEnd = function (skipReposition) {
|
||
if (onEnd.ok) return;
|
||
onEnd.ok = true;
|
||
|
||
skipReposition || stageShaftReposition(true);
|
||
|
||
if (!silent) {
|
||
triggerEvent('showend', {
|
||
user: options.user
|
||
});
|
||
}
|
||
|
||
if (!skipReposition && o_transition && o_transition !== opts.transition) {
|
||
that.setOptions({transition: o_transition});
|
||
o_transition = false;
|
||
return;
|
||
}
|
||
|
||
updateFotoramaState();
|
||
loadImg(activeIndexes, 'stage');
|
||
|
||
updateTouchTails('go', false);
|
||
stageWheelUpdate();
|
||
|
||
stageCursor();
|
||
releaseAutoplay();
|
||
changeAutoplay();
|
||
|
||
if (that.fullScreen) {
|
||
activeFrame[STAGE_FRAME_KEY].find('.' + imgFullClass).attr('aria-hidden', false);
|
||
activeFrame[STAGE_FRAME_KEY].find('.' + imgClass).attr('aria-hidden', true)
|
||
} else {
|
||
activeFrame[STAGE_FRAME_KEY].find('.' + imgFullClass).attr('aria-hidden', true);
|
||
activeFrame[STAGE_FRAME_KEY].find('.' + imgClass).attr('aria-hidden', false)
|
||
}
|
||
};
|
||
|
||
if (!o_fade) {
|
||
slide($stageShaft, {
|
||
pos: -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex),
|
||
overPos: overPos,
|
||
time: time,
|
||
onEnd: onEnd
|
||
});
|
||
} else {
|
||
var $activeFrame = activeFrame[STAGE_FRAME_KEY],
|
||
$prevActiveFrame = data[lastActiveIndex] && activeIndex !== lastActiveIndex ? data[lastActiveIndex][STAGE_FRAME_KEY] : null;
|
||
|
||
fade($activeFrame, $prevActiveFrame, $stageFrame, {
|
||
time: time,
|
||
method: opts.transition,
|
||
onEnd: onEnd
|
||
}, fadeStack);
|
||
}
|
||
|
||
arrsUpdate();
|
||
};
|
||
|
||
that.showNav = function(silent, options, time){
|
||
thumbArrUpdate();
|
||
if (o_nav) {
|
||
navUpdate();
|
||
|
||
var guessIndex = limitIndex(activeIndex + minMaxLimit(dirtyIndex - lastActiveIndex, -1, 1));
|
||
slideNavShaft({
|
||
time: time,
|
||
coo: guessIndex !== activeIndex && options.coo,
|
||
guessIndex: typeof options.coo !== 'undefined' ? guessIndex : activeIndex,
|
||
keep: silent
|
||
});
|
||
if (o_navThumbs) slideThumbBorder(time);
|
||
}
|
||
};
|
||
|
||
that.show = function (options, e) {
|
||
that.longPress.singlePressInProgress = true;
|
||
|
||
var index = calcActiveIndex(options);
|
||
calcGlobalIndexes(index);
|
||
var time = calcTime(options);
|
||
var _activeFrame = activeFrame;
|
||
that.activeFrame = activeFrame = data[activeIndex];
|
||
|
||
var silent = _activeFrame === activeFrame && !options.user;
|
||
|
||
that.showStage(silent, options, time, e);
|
||
that.showNav(silent, options, time);
|
||
|
||
showedFLAG = typeof lastActiveIndex !== 'undefined' && lastActiveIndex !== activeIndex;
|
||
lastActiveIndex = activeIndex;
|
||
that.longPress.singlePressInProgress = false;
|
||
|
||
return this;
|
||
};
|
||
|
||
that.requestFullScreen = function () {
|
||
if (o_allowFullScreen && !that.fullScreen) {
|
||
|
||
//check that this is not video
|
||
if(isVideo()) {
|
||
return;
|
||
}
|
||
|
||
scrollTop = $WINDOW.scrollTop();
|
||
scrollLeft = $WINDOW.scrollLeft();
|
||
|
||
lockScroll($WINDOW);
|
||
|
||
updateTouchTails('x', true);
|
||
|
||
measuresStash = $.extend({}, measures);
|
||
|
||
$fotorama
|
||
.addClass(fullscreenClass)
|
||
.appendTo($BODY.addClass(_fullscreenClass));
|
||
|
||
$HTML.addClass(_fullscreenClass);
|
||
|
||
unloadVideo($videoPlaying, true, true);
|
||
|
||
that.fullScreen = true;
|
||
|
||
if (o_nativeFullScreen) {
|
||
fullScreenApi.request(fotorama);
|
||
}
|
||
|
||
loadImg(activeIndexes, 'stage');
|
||
updateFotoramaState();
|
||
triggerEvent('fullscreenenter');
|
||
that.resize();
|
||
|
||
if (!('ontouchstart' in window)) {
|
||
$fullscreenIcon.focus();
|
||
}
|
||
}
|
||
|
||
return this;
|
||
};
|
||
|
||
function cancelFullScreen() {
|
||
if (that.fullScreen) {
|
||
that.fullScreen = false;
|
||
|
||
if (FULLSCREEN) {
|
||
fullScreenApi.cancel(fotorama);
|
||
}
|
||
|
||
$BODY.removeClass(_fullscreenClass);
|
||
$HTML.removeClass(_fullscreenClass);
|
||
|
||
$fotorama
|
||
.removeClass(fullscreenClass)
|
||
.insertAfter($anchor);
|
||
|
||
measures = $.extend({}, measuresStash);
|
||
|
||
unloadVideo($videoPlaying, true, true);
|
||
|
||
updateTouchTails('x', false);
|
||
|
||
that.resize();
|
||
loadImg(activeIndexes, 'stage');
|
||
|
||
lockScroll($WINDOW, scrollLeft, scrollTop);
|
||
|
||
triggerEvent('fullscreenexit');
|
||
}
|
||
}
|
||
|
||
that.cancelFullScreen = function () {
|
||
if (o_nativeFullScreen && fullScreenApi.is()) {
|
||
fullScreenApi.cancel(document);
|
||
} else {
|
||
cancelFullScreen();
|
||
}
|
||
|
||
return this;
|
||
};
|
||
|
||
that.toggleFullScreen = function () {
|
||
return that[(that.fullScreen ? 'cancel' : 'request') + 'FullScreen']();
|
||
};
|
||
|
||
that.resize = function (options) {
|
||
if (!data) return this;
|
||
|
||
var time = arguments[1] || 0,
|
||
setFLAG = arguments[2];
|
||
|
||
thumbsPerSlide = getThumbsInSlide($wrap, opts);
|
||
extendMeasures(!that.fullScreen ? optionsToLowerCase(options) : {
|
||
width: $(window).width(),
|
||
maxwidth: null,
|
||
minwidth: null,
|
||
height: $(window).height(),
|
||
maxheight: null,
|
||
minheight: null
|
||
}, [measures, setFLAG || that.fullScreen || opts]);
|
||
|
||
var width = measures.width,
|
||
height = measures.height,
|
||
ratio = measures.ratio,
|
||
windowHeight = $WINDOW.height() - (o_nav ? $nav.height() : 0);
|
||
|
||
if (measureIsValid(width)) {
|
||
$wrap.css({width: ''});
|
||
$stage.css({width: ''});
|
||
$stageShaft.css({width: ''});
|
||
$nav.css({width: ''});
|
||
$wrap.css({minWidth: measures.minwidth || 0, maxWidth: measures.maxwidth || MAX_WIDTH});
|
||
|
||
if (o_nav === 'dots') {
|
||
$navWrap.hide();
|
||
}
|
||
width = measures.W = measures.w = $wrap.width();
|
||
measures.nw = o_nav && numberFromWhatever(opts.navwidth, width) || width;
|
||
|
||
$stageShaft.css({width: measures.w, marginLeft: (measures.W - measures.w) / 2});
|
||
|
||
height = numberFromWhatever(height, windowHeight);
|
||
|
||
height = height || (ratio && width / ratio);
|
||
|
||
if (height) {
|
||
width = Math.round(width);
|
||
height = measures.h = Math.round(minMaxLimit(height, numberFromWhatever(measures.minheight, windowHeight), numberFromWhatever(measures.maxheight, windowHeight)));
|
||
$stage.css({'width': width, 'height': height});
|
||
|
||
if (opts.navdir === 'vertical' && !that.fullscreen) {
|
||
$nav.width(opts.thumbwidth + opts.thumbmargin * 2);
|
||
}
|
||
|
||
if (opts.navdir === 'horizontal' && !that.fullscreen) {
|
||
$nav.height(opts.thumbheight + opts.thumbmargin * 2);
|
||
}
|
||
|
||
if (o_nav === 'dots') {
|
||
$nav.width(width)
|
||
.height('auto');
|
||
$navWrap.show();
|
||
}
|
||
|
||
if (opts.navdir === 'vertical' && that.fullScreen) {
|
||
$stage.css('height', $WINDOW.height());
|
||
}
|
||
|
||
if (opts.navdir === 'horizontal' && that.fullScreen) {
|
||
$stage.css('height', $WINDOW.height() - $nav.height());
|
||
}
|
||
|
||
if (o_nav) {
|
||
switch (opts.navdir) {
|
||
case 'vertical':
|
||
$navWrap.removeClass(navShafthorizontalClass);
|
||
$navWrap.removeClass(navShaftListClass);
|
||
$navWrap.addClass(navShaftVerticalClass);
|
||
$nav
|
||
.stop()
|
||
.animate({height: measures.h, width: opts.thumbwidth}, time);
|
||
break;
|
||
case 'list':
|
||
$navWrap.removeClass(navShaftVerticalClass);
|
||
$navWrap.removeClass(navShafthorizontalClass);
|
||
$navWrap.addClass(navShaftListClass);
|
||
break;
|
||
default:
|
||
$navWrap.removeClass(navShaftVerticalClass);
|
||
$navWrap.removeClass(navShaftListClass);
|
||
$navWrap.addClass(navShafthorizontalClass);
|
||
$nav
|
||
.stop()
|
||
.animate({width: measures.nw}, time);
|
||
break;
|
||
}
|
||
|
||
stageShaftReposition();
|
||
slideNavShaft({guessIndex: activeIndex, time: time, keep: true});
|
||
if (o_navThumbs && frameAppend.nav) slideThumbBorder(time);
|
||
}
|
||
|
||
measuresSetFLAG = setFLAG || true;
|
||
|
||
ready.ok = true;
|
||
ready();
|
||
}
|
||
}
|
||
|
||
stageLeft = $stage.offset().left;
|
||
setStagePosition();
|
||
|
||
return this;
|
||
};
|
||
|
||
that.setOptions = function (options) {
|
||
$.extend(opts, options);
|
||
reset();
|
||
return this;
|
||
};
|
||
|
||
that.shuffle = function () {
|
||
data && shuffle(data) && reset();
|
||
return this;
|
||
};
|
||
|
||
function setShadow($el, edge) {
|
||
if (o_shadows) {
|
||
$el.removeClass(shadowsLeftClass + ' ' + shadowsRightClass);
|
||
$el.removeClass(shadowsTopClass + ' ' + shadowsBottomClass);
|
||
edge && !$videoPlaying && $el.addClass(edge.replace(/^|\s/g, ' ' + shadowsClass + '--'));
|
||
}
|
||
}
|
||
|
||
that.longPress = {
|
||
threshold: 1,
|
||
count: 0,
|
||
thumbSlideTime: 20,
|
||
progress: function(){
|
||
if (!this.inProgress) {
|
||
this.count++;
|
||
this.inProgress = this.count > this.threshold;
|
||
}
|
||
},
|
||
end: function(){
|
||
if(this.inProgress) {
|
||
this.isEnded = true
|
||
}
|
||
},
|
||
reset: function(){
|
||
this.count = 0;
|
||
this.inProgress = false;
|
||
this.isEnded = false;
|
||
}
|
||
};
|
||
|
||
that.destroy = function () {
|
||
that.cancelFullScreen();
|
||
that.stopAutoplay();
|
||
|
||
data = that.data = null;
|
||
|
||
appendElements();
|
||
|
||
activeIndexes = [];
|
||
detachFrames(STAGE_FRAME_KEY);
|
||
|
||
reset.ok = false;
|
||
|
||
return this;
|
||
};
|
||
|
||
/**
|
||
*
|
||
* @returns {jQuery.Fotorama}
|
||
*/
|
||
that.playVideo = function () {
|
||
var dataFrame = activeFrame,
|
||
video = dataFrame.video,
|
||
_activeIndex = activeIndex;
|
||
|
||
if (typeof video === 'object' && dataFrame.videoReady) {
|
||
o_nativeFullScreen && that.fullScreen && that.cancelFullScreen();
|
||
|
||
waitFor(function () {
|
||
return !fullScreenApi.is() || _activeIndex !== activeIndex;
|
||
}, function () {
|
||
if (_activeIndex === activeIndex) {
|
||
dataFrame.$video = dataFrame.$video || $(div(videoClass)).append(createVideoFrame(video));
|
||
dataFrame.$video.appendTo(dataFrame[STAGE_FRAME_KEY]);
|
||
|
||
$wrap.addClass(wrapVideoClass);
|
||
$videoPlaying = dataFrame.$video;
|
||
|
||
stageNoMove();
|
||
|
||
$arrs.blur();
|
||
$fullscreenIcon.blur();
|
||
|
||
triggerEvent('loadvideo');
|
||
}
|
||
});
|
||
}
|
||
|
||
return this;
|
||
};
|
||
|
||
that.stopVideo = function () {
|
||
unloadVideo($videoPlaying, true, true);
|
||
return this;
|
||
};
|
||
|
||
that.spliceByIndex = function (index, newImgObj) {
|
||
newImgObj.i = index + 1;
|
||
newImgObj.img && $.ajax({
|
||
url: newImgObj.img,
|
||
type: 'HEAD',
|
||
success: function () {
|
||
data.splice(index, 1, newImgObj);
|
||
reset();
|
||
}
|
||
});
|
||
};
|
||
|
||
function unloadVideo($video, unloadActiveFLAG, releaseAutoplayFLAG) {
|
||
if (unloadActiveFLAG) {
|
||
$wrap.removeClass(wrapVideoClass);
|
||
$videoPlaying = false;
|
||
|
||
stageNoMove();
|
||
}
|
||
|
||
if ($video && $video !== $videoPlaying) {
|
||
$video.remove();
|
||
triggerEvent('unloadvideo');
|
||
}
|
||
|
||
if (releaseAutoplayFLAG) {
|
||
releaseAutoplay();
|
||
changeAutoplay();
|
||
}
|
||
}
|
||
|
||
function toggleControlsClass(FLAG) {
|
||
$wrap.toggleClass(wrapNoControlsClass, FLAG);
|
||
}
|
||
|
||
function stageCursor(e) {
|
||
if (stageShaftTouchTail.flow) return;
|
||
|
||
var x = e ? e.pageX : stageCursor.x,
|
||
pointerFLAG = x && !disableDirrection(getDirection(x)) && opts.click;
|
||
|
||
if (stageCursor.p !== pointerFLAG
|
||
&& $stage.toggleClass(pointerClass, pointerFLAG)) {
|
||
stageCursor.p = pointerFLAG;
|
||
stageCursor.x = x;
|
||
}
|
||
}
|
||
|
||
$stage.on('mousemove', stageCursor);
|
||
|
||
function clickToShow(showOptions, e) {
|
||
clearTimeout(clickToShow.t);
|
||
|
||
if (opts.clicktransition && opts.clicktransition !== opts.transition) {
|
||
setTimeout(function () {
|
||
var _o_transition = opts.transition;
|
||
|
||
that.setOptions({transition: opts.clicktransition});
|
||
|
||
// now safe to pass base transition to o_transition, so that.show will restor it
|
||
o_transition = _o_transition;
|
||
// this timeout is here to prevent jerking in some browsers
|
||
clickToShow.t = setTimeout(function () {
|
||
that.show(showOptions);
|
||
}, 10);
|
||
}, 0);
|
||
} else {
|
||
that.show(showOptions, e);
|
||
}
|
||
}
|
||
|
||
function onStageTap(e, toggleControlsFLAG) {
|
||
var target = e.target,
|
||
$target = $(target);
|
||
if ($target.hasClass(videoPlayClass)) {
|
||
that.playVideo();
|
||
} else if (target === fullscreenIcon) {
|
||
that.toggleFullScreen();
|
||
} else if ($videoPlaying) {
|
||
target === videoClose && unloadVideo($videoPlaying, true, true);
|
||
} else if (!$fotorama.hasClass(fullscreenClass)) {
|
||
that.requestFullScreen();
|
||
}
|
||
}
|
||
|
||
function updateTouchTails(key, value) {
|
||
stageShaftTouchTail[key] = navShaftTouchTail[key] = value;
|
||
}
|
||
|
||
stageShaftTouchTail = moveOnTouch($stageShaft, {
|
||
onStart: onTouchStart,
|
||
onMove: function (e, result) {
|
||
setShadow($stage, result.edge);
|
||
},
|
||
onTouchEnd: onTouchEnd,
|
||
onEnd: function (result) {
|
||
var toggleControlsFLAG;
|
||
|
||
setShadow($stage);
|
||
toggleControlsFLAG = (MS_POINTER && !hoverFLAG || result.touch) &&
|
||
opts.arrows;
|
||
|
||
if ((result.moved || (toggleControlsFLAG && result.pos !== result.newPos && !result.control)) && result.$target[0] !== $fullscreenIcon[0]) {
|
||
var index = getIndexByPos(result.newPos, measures.w, opts.margin, repositionIndex);
|
||
|
||
that.show({
|
||
index: index,
|
||
time: o_fade ? o_transitionDuration : result.time,
|
||
overPos: result.overPos,
|
||
user: true
|
||
});
|
||
} else if (!result.aborted && !result.control) {
|
||
onStageTap(result.startEvent, toggleControlsFLAG);
|
||
}
|
||
},
|
||
timeLow: 1,
|
||
timeHigh: 1,
|
||
friction: 2,
|
||
select: '.' + selectClass + ', .' + selectClass + ' *',
|
||
$wrap: $stage,
|
||
direction: 'horizontal'
|
||
|
||
});
|
||
|
||
navShaftTouchTail = moveOnTouch($navShaft, {
|
||
onStart: onTouchStart,
|
||
onMove: function (e, result) {
|
||
setShadow($nav, result.edge);
|
||
},
|
||
onTouchEnd: onTouchEnd,
|
||
onEnd: function (result) {
|
||
|
||
function onEnd() {
|
||
slideNavShaft.l = result.newPos;
|
||
releaseAutoplay();
|
||
changeAutoplay();
|
||
thumbsDraw(result.newPos, true);
|
||
thumbArrUpdate();
|
||
}
|
||
|
||
if (!result.moved) {
|
||
var target = result.$target.closest('.' + navFrameClass, $navShaft)[0];
|
||
target && onNavFrameClick.call(target, result.startEvent);
|
||
} else if (result.pos !== result.newPos) {
|
||
pausedAutoplayFLAG = true;
|
||
slide($navShaft, {
|
||
time: result.time,
|
||
pos: result.newPos,
|
||
overPos: result.overPos,
|
||
direction: opts.navdir,
|
||
onEnd: onEnd
|
||
});
|
||
thumbsDraw(result.newPos);
|
||
o_shadows && setShadow($nav, findShadowEdge(result.newPos, navShaftTouchTail.min, navShaftTouchTail.max, result.dir));
|
||
} else {
|
||
onEnd();
|
||
}
|
||
},
|
||
timeLow: .5,
|
||
timeHigh: 2,
|
||
friction: 5,
|
||
$wrap: $nav,
|
||
direction: opts.navdir
|
||
});
|
||
|
||
stageWheelTail = wheel($stage, {
|
||
shift: true,
|
||
onEnd: function (e, direction) {
|
||
onTouchStart();
|
||
onTouchEnd();
|
||
that.show({index: direction, slow: e.altKey})
|
||
}
|
||
});
|
||
|
||
navWheelTail = wheel($nav, {
|
||
onEnd: function (e, direction) {
|
||
onTouchStart();
|
||
onTouchEnd();
|
||
var newPos = stop($navShaft) + direction * .25;
|
||
$navShaft.css(getTranslate(minMaxLimit(newPos, navShaftTouchTail.min, navShaftTouchTail.max), opts.navdir));
|
||
o_shadows && setShadow($nav, findShadowEdge(newPos, navShaftTouchTail.min, navShaftTouchTail.max, opts.navdir));
|
||
navWheelTail.prevent = {'<': newPos >= navShaftTouchTail.max, '>': newPos <= navShaftTouchTail.min};
|
||
clearTimeout(navWheelTail.t);
|
||
navWheelTail.t = setTimeout(function () {
|
||
slideNavShaft.l = newPos;
|
||
thumbsDraw(newPos, true)
|
||
}, TOUCH_TIMEOUT);
|
||
thumbsDraw(newPos);
|
||
}
|
||
});
|
||
|
||
$wrap.hover(
|
||
function () {
|
||
setTimeout(function () {
|
||
if (touchedFLAG) return;
|
||
toggleControlsClass(!(hoverFLAG = true));
|
||
}, 0);
|
||
},
|
||
function () {
|
||
if (!hoverFLAG) return;
|
||
toggleControlsClass(!(hoverFLAG = false));
|
||
}
|
||
);
|
||
|
||
function onNavFrameClick(e) {
|
||
var index = $(this).data().eq;
|
||
|
||
if (opts.navtype === 'thumbs') {
|
||
clickToShow({index: index, slow: e.altKey, user: true, coo: e._x - $nav.offset().left});
|
||
} else {
|
||
clickToShow({index: index, slow: e.altKey, user: true});
|
||
}
|
||
}
|
||
|
||
function onArrClick(e) {
|
||
clickToShow({index: $arrs.index(this) ? '>' : '<', slow: e.altKey, user: true});
|
||
}
|
||
|
||
smartClick($arrs, function (e) {
|
||
stopEvent(e);
|
||
onArrClick.call(this, e);
|
||
}, {
|
||
onStart: function () {
|
||
onTouchStart();
|
||
stageShaftTouchTail.control = true;
|
||
},
|
||
onTouchEnd: onTouchEnd
|
||
});
|
||
|
||
smartClick($thumbArrLeft, function (e) {
|
||
stopEvent(e);
|
||
if (opts.navtype === 'thumbs') {
|
||
|
||
that.show('<');
|
||
} else {
|
||
that.showSlide('prev')
|
||
}
|
||
});
|
||
|
||
smartClick($thumbArrRight, function (e) {
|
||
stopEvent(e);
|
||
if (opts.navtype === 'thumbs') {
|
||
that.show('>');
|
||
} else {
|
||
that.showSlide('next')
|
||
}
|
||
|
||
});
|
||
|
||
|
||
function addFocusOnControls(el) {
|
||
addFocus(el, function () {
|
||
setTimeout(function () {
|
||
lockScroll($stage);
|
||
}, 0);
|
||
toggleControlsClass(false);
|
||
});
|
||
}
|
||
|
||
$arrs.each(function () {
|
||
addEnterUp(this, function (e) {
|
||
onArrClick.call(this, e);
|
||
});
|
||
addFocusOnControls(this);
|
||
});
|
||
|
||
addEnterUp(fullscreenIcon, function () {
|
||
if ($fotorama.hasClass(fullscreenClass)) {
|
||
that.cancelFullScreen();
|
||
$stageShaft.focus();
|
||
} else {
|
||
that.requestFullScreen();
|
||
$fullscreenIcon.focus();
|
||
}
|
||
|
||
});
|
||
addFocusOnControls(fullscreenIcon);
|
||
|
||
function reset() {
|
||
setData();
|
||
setOptions();
|
||
|
||
if (!reset.i) {
|
||
reset.i = true;
|
||
// Only once
|
||
var _startindex = opts.startindex;
|
||
activeIndex = repositionIndex = dirtyIndex = lastActiveIndex = startIndex = edgeIndex(_startindex) || 0;
|
||
/*(o_rtl ? size - 1 : 0)*///;
|
||
}
|
||
|
||
if (size) {
|
||
if (changeToRtl()) return;
|
||
|
||
if ($videoPlaying) {
|
||
unloadVideo($videoPlaying, true);
|
||
}
|
||
|
||
activeIndexes = [];
|
||
|
||
if (!isVideo()) {
|
||
detachFrames(STAGE_FRAME_KEY);
|
||
}
|
||
|
||
reset.ok = true;
|
||
|
||
that.show({index: activeIndex, time: 0});
|
||
that.resize();
|
||
} else {
|
||
that.destroy();
|
||
}
|
||
}
|
||
|
||
function changeToRtl() {
|
||
|
||
if (!changeToRtl.f === o_rtl) {
|
||
changeToRtl.f = o_rtl;
|
||
activeIndex = size - 1 - activeIndex;
|
||
that.reverse();
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
$.each('load push pop shift unshift reverse sort splice'.split(' '), function (i, method) {
|
||
that[method] = function () {
|
||
data = data || [];
|
||
if (method !== 'load') {
|
||
Array.prototype[method].apply(data, arguments);
|
||
} else if (arguments[0] && typeof arguments[0] === 'object' && arguments[0].length) {
|
||
data = clone(arguments[0]);
|
||
}
|
||
reset();
|
||
return that;
|
||
}
|
||
});
|
||
|
||
function ready() {
|
||
if (ready.ok) {
|
||
ready.ok = false;
|
||
triggerEvent('ready');
|
||
}
|
||
}
|
||
|
||
reset();
|
||
};
|
||
$.fn.fotorama = function (opts) {
|
||
return this.each(function () {
|
||
var that = this,
|
||
$fotorama = $(this),
|
||
fotoramaData = $fotorama.data(),
|
||
fotorama = fotoramaData.fotorama;
|
||
|
||
if (!fotorama) {
|
||
waitFor(function () {
|
||
return !isHidden(that);
|
||
}, function () {
|
||
fotoramaData.urtext = $fotorama.html();
|
||
new $.Fotorama($fotorama,
|
||
$.extend(
|
||
{},
|
||
OPTIONS,
|
||
window.fotoramaDefaults,
|
||
opts,
|
||
fotoramaData
|
||
)
|
||
);
|
||
});
|
||
} else {
|
||
fotorama.setOptions(opts, true);
|
||
}
|
||
});
|
||
};
|
||
$.Fotorama.instances = [];
|
||
|
||
function calculateIndexes() {
|
||
$.each($.Fotorama.instances, function (index, instance) {
|
||
instance.index = index;
|
||
});
|
||
}
|
||
|
||
function addInstance(instance) {
|
||
$.Fotorama.instances.push(instance);
|
||
calculateIndexes();
|
||
}
|
||
|
||
function hideInstance(instance) {
|
||
$.Fotorama.instances.splice(instance.index, 1);
|
||
calculateIndexes();
|
||
}
|
||
|
||
$.Fotorama.cache = {};
|
||
$.Fotorama.measures = {};
|
||
$ = $ || {};
|
||
$.Fotorama = $.Fotorama || {};
|
||
$.Fotorama.jst = $.Fotorama.jst || {};
|
||
|
||
$.Fotorama.jst.dots = function (v) {
|
||
var __t, __p = '', __e = _.escape;
|
||
__p += '<div class="fotorama__nav__frame fotorama__nav__frame--dot" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n <div class="fotorama__dot"></div>\r\n</div>';
|
||
return __p
|
||
};
|
||
|
||
$.Fotorama.jst.frameCaption = function (v) {
|
||
var __t, __p = '', __e = _.escape;
|
||
__p += '<div class="fotorama__caption" aria-hidden="true">\r\n <div class="fotorama__caption__wrap" id="' +
|
||
((__t = ( v.labelledby )) == null ? '' : __t) +
|
||
'">' +
|
||
((__t = ( v.caption )) == null ? '' : __t) +
|
||
'</div>\r\n</div>\r\n';
|
||
return __p
|
||
};
|
||
|
||
$.Fotorama.jst.style = function (v) {
|
||
var __t, __p = '', __e = _.escape;
|
||
__p += '.fotorama' +
|
||
((__t = ( v.s )) == null ? '' : __t) +
|
||
' .fotorama__nav--thumbs .fotorama__nav__frame{\r\npadding:' +
|
||
((__t = ( v.m )) == null ? '' : __t) +
|
||
'px;\r\nheight:' +
|
||
((__t = ( v.h )) == null ? '' : __t) +
|
||
'px}\r\n.fotorama' +
|
||
((__t = ( v.s )) == null ? '' : __t) +
|
||
' .fotorama__thumb-border{\r\nheight:' +
|
||
((__t = ( v.h )) == null ? '' : __t) +
|
||
'px;\r\nborder-width:' +
|
||
((__t = ( v.b )) == null ? '' : __t) +
|
||
'px;\r\nmargin-top:' +
|
||
((__t = ( v.m )) == null ? '' : __t) +
|
||
'px}';
|
||
return __p
|
||
};
|
||
|
||
$.Fotorama.jst.thumb = function (v) {
|
||
var __t, __p = '', __e = _.escape;
|
||
__p += '<div class="fotorama__nav__frame fotorama__nav__frame--thumb" tabindex="0" role="button" data-gallery-role="nav-frame" data-nav-type="thumb" aria-label>\r\n <div class="fotorama__thumb">\r\n </div>\r\n</div>';
|
||
return __p
|
||
};
|
||
})(window, document, location, typeof jQuery !== 'undefined' && jQuery);
|