wikipoints/public/js/fotorama.js

3706 lines
100 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* Fotorama 4.6.3 | http://fotorama.io/license/
*/
fotoramaVersion = '4.6.3';
(function (window, document, location, $, undefined) {
"use strict";
var _fotoramaClass = 'fotorama',
_fullscreenClass = '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',
arrArrClass = arrClass + '__arr',
navClass = _fotoramaClass + '__nav',
navWrapClass = navClass + '-wrap',
navShaftClass = navClass + '__shaft',
navDotsClass = navClass + '--dots',
navThumbsClass = navClass + '--thumbs',
navFrameClass = navClass + '__frame',
navFrameDotClass = navFrameClass + '--dot',
navFrameThumbClass = navFrameClass + '--thumb',
fadeClass = _fotoramaClass + '__fade',
fadeFrontClass = fadeClass + '-front',
fadeRearClass = fadeClass + '-rear',
shadowClass = _fotoramaClass + '__shadow',
shadowsClass = shadowClass + 's',
shadowsLeftClass = shadowsClass + '--left',
shadowsRightClass = shadowsClass + '--right',
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',
dotClass = _fotoramaClass + '__dot',
thumbClass = _fotoramaClass + '__thumb',
thumbBorderClass = thumbClass + '-border',
htmlClass = _fotoramaClass + '__html',
videoClass = _fotoramaClass + '__video',
videoPlayClass = videoClass + '-play',
videoCloseClass = videoClass + '-close',
captionClass = _fotoramaClass + '__caption',
captionWrapClass = _fotoramaClass + '__caption__wrap',
spinnerClass = _fotoramaClass + '__spinner',
buttonAttributes = '" tabindex="0" role="button';
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.';
}
// My Underscore :-)
var _ = {};
/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
* Build: http://modernizr.com/download/#-csstransforms3d-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes
*/
var Modernizr = (function (window, document, undefined) {
var version = '2.6.2',
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 = ['&#173;', '<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['csstransforms3d'] = function () {
var ret = !!testPropsAll('perspective');
// Chrome fails that test, ignore
// 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;
};
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) {
return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
};
}
//fgnass.github.com/spin.js#v1.3.2
/**
* Copyright (c) 2011-2013 Felix Gnass
* Licensed under the MIT license
*/
var Spinner,
spinnerDefaults = {
lines: 12, // The number of lines to draw
length: 5, // The length of each line
width: 2, // The line thickness
radius: 7, // The radius of the inner circle
corners: 1, // Corner roundness (0..1)
rotate: 15, // The rotation offset
color: 'rgba(128, 128, 128, .75)',
hwaccel: true
},
spinnerOverride = {
top: 'auto',
left: 'auto',
className: ''
};
(function(root, factory) {
/* CommonJS */
//if (typeof exports == 'object') module.exports = factory()
/* AMD module */
//else if (typeof define == 'function' && define.amd) define(factory)
/* Browser global */
//else root.Spinner = factory()
Spinner = factory();
}
(this, function() {
"use strict";
var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */
, animations = {} /* Animation rules keyed by their name */
, useCssAnimations /* Whether to use CSS animations or setTimeout */
/**
* Utility function to create elements. If no tag name is given,
* a DIV is created. Optionally properties can be passed.
*/
function createEl(tag, prop) {
var el = document.createElement(tag || 'div')
, n
for(n in prop) el[n] = prop[n]
return el
}
/**
* Appends children and returns the parent.
*/
function ins(parent /* child1, child2, ...*/) {
for (var i=1, n=arguments.length; i<n; i++)
parent.appendChild(arguments[i])
return parent
}
/**
* Insert a new stylesheet to hold the @keyframe or VML rules.
*/
var sheet = (function() {
var el = createEl('style', {type : 'text/css'})
ins(document.getElementsByTagName('head')[0], el)
return el.sheet || el.styleSheet
}())
/**
* Creates an opacity keyframe animation rule and returns its name.
* Since most mobile Webkits have timing issues with animation-delay,
* we create separate rules for each line/segment.
*/
function addAnimation(alpha, trail, i, lines) {
var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-')
, start = 0.01 + i/lines * 100
, z = Math.max(1 - (1-alpha) / trail * (100-start), alpha)
, prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase()
, pre = prefix && '-' + prefix + '-' || ''
if (!animations[name]) {
sheet.insertRule(
'@' + pre + 'keyframes ' + name + '{' +
'0%{opacity:' + z + '}' +
start + '%{opacity:' + alpha + '}' +
(start+0.01) + '%{opacity:1}' +
(start+trail) % 100 + '%{opacity:' + alpha + '}' +
'100%{opacity:' + z + '}' +
'}', sheet.cssRules.length)
animations[name] = 1
}
return name
}
/**
* Tries various vendor prefixes and returns the first supported property.
*/
function vendor(el, prop) {
var s = el.style
, pp
, i
prop = prop.charAt(0).toUpperCase() + prop.slice(1)
for(i=0; i<prefixes.length; i++) {
pp = prefixes[i]+prop
if(s[pp] !== undefined) return pp
}
if(s[prop] !== undefined) return prop
}
/**
* Sets multiple style properties at once.
*/
function css(el, prop) {
for (var n in prop)
el.style[vendor(el, n)||n] = prop[n]
return el
}
/**
* Fills in default values.
*/
function merge(obj) {
for (var i=1; i < arguments.length; i++) {
var def = arguments[i]
for (var n in def)
if (obj[n] === undefined) obj[n] = def[n]
}
return obj
}
/**
* Returns the absolute page-offset of the given element.
*/
function pos(el) {
var o = { x:el.offsetLeft, y:el.offsetTop }
while((el = el.offsetParent))
o.x+=el.offsetLeft, o.y+=el.offsetTop
return o
}
/**
* Returns the line color from the given string or array.
*/
function getColor(color, idx) {
return typeof color == 'string' ? color : color[idx % color.length]
}
// Built-in defaults
var defaults = {
lines: 12, // The number of lines to draw
length: 7, // The length of each line
width: 5, // The line thickness
radius: 10, // The radius of the inner circle
rotate: 0, // Rotation offset
corners: 1, // Roundness (0..1)
color: '#000', // #rgb or #rrggbb
direction: 1, // 1: clockwise, -1: counterclockwise
speed: 1, // Rounds per second
trail: 100, // Afterglow percentage
opacity: 1/4, // Opacity of the lines
fps: 20, // Frames per second when using setTimeout()
zIndex: 2e9, // Use a high z-index by default
className: 'spinner', // CSS class to assign to the element
top: 'auto', // center vertically
left: 'auto', // center horizontally
position: 'relative' // element position
}
/** The constructor */
function Spinner(o) {
if (typeof this == 'undefined') return new Spinner(o)
this.opts = merge(o || {}, Spinner.defaults, defaults)
}
// Global defaults that override the built-ins:
Spinner.defaults = {}
merge(Spinner.prototype, {
/**
* Adds the spinner to the given target element. If this instance is already
* spinning, it is automatically removed from its previous target b calling
* stop() internally.
*/
spin: function(target) {
this.stop()
var self = this
, o = self.opts
, el = self.el = css(createEl(0, {className: o.className}), {position: o.position, width: 0, zIndex: o.zIndex})
, mid = o.radius+o.length+o.width
, ep // element position
, tp // target position
if (target) {
target.insertBefore(el, target.firstChild||null)
tp = pos(target)
ep = pos(el)
css(el, {
left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : parseInt(o.left, 10) + mid) + 'px',
top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : parseInt(o.top, 10) + mid) + 'px'
})
}
el.setAttribute('role', 'progressbar')
self.lines(el, self.opts)
if (!useCssAnimations) {
// No CSS animation support, use setTimeout() instead
var i = 0
, start = (o.lines - 1) * (1 - o.direction) / 2
, alpha
, fps = o.fps
, f = fps/o.speed
, ostep = (1-o.opacity) / (f*o.trail / 100)
, astep = f/o.lines
;(function anim() {
i++;
for (var j = 0; j < o.lines; j++) {
alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity)
self.opacity(el, j * o.direction + start, alpha, o)
}
self.timeout = self.el && setTimeout(anim, ~~(1000/fps))
})()
}
return self
},
/**
* Stops and removes the Spinner.
*/
stop: function() {
var el = this.el
if (el) {
clearTimeout(this.timeout)
if (el.parentNode) el.parentNode.removeChild(el)
this.el = undefined
}
return this
},
/**
* Internal method that draws the individual lines. Will be overwritten
* in VML fallback mode below.
*/
lines: function(el, o) {
var i = 0
, start = (o.lines - 1) * (1 - o.direction) / 2
, seg
function fill(color, shadow) {
return css(createEl(), {
position: 'absolute',
width: (o.length+o.width) + 'px',
height: o.width + 'px',
background: color,
boxShadow: shadow,
transformOrigin: 'left',
transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
borderRadius: (o.corners * o.width>>1) + 'px'
})
}
for (; i < o.lines; i++) {
seg = css(createEl(), {
position: 'absolute',
top: 1+~(o.width/2) + 'px',
transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
opacity: o.opacity,
animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite'
})
if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}))
ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)')))
}
return el
},
/**
* Internal method that adjusts the opacity of a single line.
* Will be overwritten in VML fallback mode below.
*/
opacity: function(el, i, val) {
if (i < el.childNodes.length) el.childNodes[i].style.opacity = val
}
})
function initVML() {
/* Utility function to create a VML tag */
function vml(tag, attr) {
return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr)
}
// No CSS transforms but VML support, add a CSS rule for VML elements:
sheet.addRule('.spin-vml', 'behavior:url(#default#VML)')
Spinner.prototype.lines = function(el, o) {
var r = o.length+o.width
, s = 2*r
function grp() {
return css(
vml('group', {
coordsize: s + ' ' + s,
coordorigin: -r + ' ' + -r
}),
{ width: s, height: s }
)
}
var margin = -(o.width+o.length)*2 + 'px'
, g = css(grp(), {position: 'absolute', top: margin, left: margin})
, i
function seg(i, dx, filter) {
ins(g,
ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
ins(css(vml('roundrect', {arcsize: o.corners}), {
width: r,
height: o.width,
left: o.radius,
top: -o.width>>1,
filter: filter
}),
vml('fill', {color: getColor(o.color, i), opacity: o.opacity}),
vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
)
)
)
}
if (o.shadow)
for (i = 1; i <= o.lines; i++)
seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)')
for (i = 1; i <= o.lines; i++) seg(i)
return ins(el, g)
}
Spinner.prototype.opacity = function(el, i, val, o) {
var c = el.firstChild
o = o.shadow && o.lines || 0
if (c && i+o < c.childNodes.length) {
c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild
if (c) c.opacity = val
}
}
}
var probe = css(createEl('group'), {behavior: 'url(#default#VML)'})
if (!vendor(probe, 'transform') && probe.adj) initVML()
else useCssAnimations = vendor(probe, 'animation')
return Spinner
}));
/* 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 = 99999,
FIFTYFIFTY = '50%',
OPTIONS = {
// dimensions
width: null, // 500 || '100%'
minwidth: null,
maxwidth: '100%', // '100%'
height: null,
minheight: null,
maxheight: null,
ratio: null, // '16/9' || 500/333 || 1.5
margin: MARGIN,
glimpse: 0,
fit: 'contain', // 'cover' || 'scaledown' || 'none'
position: FIFTYFIFTY,
thumbposition: FIFTYFIFTY,
// navigation, thumbs
nav: 'dots', // 'thumbs' || false
navposition: 'bottom', // 'top'
navwidth: null,
thumbwidth: THUMB_SIZE,
thumbheight: THUMB_SIZE,
thumbmargin: MARGIN,
thumbborderwidth: MARGIN,
thumbfit: 'cover', // 'contain' || 'scaledown' || 'none'
allowfullscreen: false, // true || 'native'
transition: 'slide', // 'crossfade' || 'dissolve'
clicktransition: null,
transitionduration: TRANSITION_DURATION,
captions: true,
hash: false,
startindex: 0,
loop: false,
autoplay: false,
stopautoplayontouch: true,
keyboard: false,
arrows: true,
click: true,
swipe: true,
trackpad: false,
enableifsingleframe: false,
controlsonstart: true,
shuffle: false,
direction: 'ltr', // 'rtl'
shadows: true,
spinner: null
},
KEYBOARD_OPTIONS = {
left: true,
right: true,
down: false,
up: false,
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) {
return css.match(/ma/) && css.match(/-?\d+(?!d)/g)[css.match(/3d/) ? 12 : 4];
}
function readPosition ($el) {
if (CSS3) {
return +readTransform($el.css('transform'));
} else {
return +$el.css('left').replace('px', '');
}
}
function getTranslate (pos/*, _001*/) {
var obj = {};
if (CSS3) {
obj.transform = 'translate3d(' + (pos/* + (_001 ? 0.001 : 0)*/) + 'px,0,0)'; // 0.001 to remove Retina artifacts
} else {
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) {
//console.log('getPosByIndex', index, side, margin, baseIndex);
//console.log((index - (baseIndex || 0)) * (side + (margin || 0)));
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, left/*, _001*/) {
if ($el.length) {
var elData = $el.data();
if (CSS3) {
$el.css(getDuration(0));
elData.onEndFn = noop;
clearTimeout(elData.tT);
} else {
$el.stop();
}
var lockedLeft = getNumber(left, function () {
return readPosition($el);
});
$el.css(getTranslate(lockedLeft/*, _001*/));//.width(); // `.width()` for reflow
return lockedLeft;
}
}
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/)) {
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/v2/video/' + video.id + '.json',
dataType: 'jsonp',
success: function (json) {
dataFrame.thumbsReady = true;
updateData(data, {img: json[0].thumbnail_large, thumb: json[0].thumbnail_small}, 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 setHash (hash) {
////console.time('setHash ' + hash);
location.replace(location.protocol
+ '//'
+ location.host
+ location.pathname.replace(/^\/?/, '/')
+ location.search
+ '#' + hash);
////console.timeEnd('setHash ' + hash);
}
function fit ($el, measuresToFit, method, position) {
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 ||
elData.l.m !== method ||
elData.l.p !== position)) {
console.log('fit');
var width = measures.width,
height = measures.height,
ratio = measuresToFit.w / measuresToFit.h,
biggerRatioFLAG = measures.ratio >= ratio,
fitFLAG = method === 'scaledown',
containFLAG = method === 'contain',
coverFLAG = method === 'cover',
pos = parsePosition(position);
if (biggerRatioFLAG && (fitFLAG || containFLAG) || !biggerRatioFLAG && coverFLAG) {
width = minMaxLimit(measuresToFit.w, 0, fitFLAG ? width : Infinity);
height = width / measures.ratio;
} else if (biggerRatioFLAG && coverFLAG || !biggerRatioFLAG && (fitFLAG || containFLAG)) {
height = minMaxLimit(measuresToFit.h, 0, fitFLAG ? height : Infinity);
width = height * measures.ratio;
}
$el.css({
width: width,
height: height,
left: numberFromWhatever(pos.x, measuresToFit.w - width),
top: numberFromWhatever(pos.y, measuresToFit.h- height)
});
elData.l = {
W: measures.width,
H: measures.height,
r: measures.ratio,
w: measuresToFit.w,
h: measuresToFit.h,
m: method,
p: position
};
}
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) {
return min === max ? false : pos <= min ? 'left' : pos >= max ? 'right' : 'left right';
}
function getIndexFromHash (hash, data, ok, startindex) {
if (!ok) return false;
if (!isNaN(hash)) return hash - (startindex ? 0 : 1);
var index;
for (var _i = 0, _l = data.length; _i < _l; _i++) {
var dataFrame = data[_i];
if (dataFrame.id === hash) {
index = _i;
break;
}
}
return index;
}
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) {
//console.log('smartClick → result.moved', result.moved);
if (result.moved) return;
fn.call(this, startEvent);
}
}), {noMove: true});
});
}
function div (classes, child) {
return '<div class="' + classes + '">' + (child || '') + '</div>';
}
// FisherYates 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);
}
function elIsDisabled (el) {
return !!el.getAttribute('disabled');
}
function disableAttr (FLAG) {
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 ? '>' : '<';
}
function parsePosition (rule) {
rule = (rule + '').split(/\s+/);
return {
x: measureIsValid(rule[0]) || FIFTYFIFTY,
y: measureIsValid(rule[1]) || FIFTYFIFTY
}
}
function slide ($el, options) {
var elData = $el.data(),
elPos = Math.round(options.pos),
onEndFn = function () {
elData.sliding = false;
(options.onEnd || noop)();
};
if (typeof options.overPos !== 'undefined' && options.overPos !== options.pos) {
elPos = options.overPos;
onEndFn = function () {
slide($el, $.extend({}, options, {overPos: options.pos, time: Math.max(TRANSITION_DURATION, options.time / 2)}))
};
}
//////console.time('var translate = $.extend');
var translate = $.extend(getTranslate(elPos/*, options._001*/), options.width && {width: options.width});
//////console.timeEnd('var translate = $.extend');
elData.sliding = true;
if (CSS3) {
$el.css($.extend(getDuration(options.time), translate));
if (options.time > 10) {
//////console.time('afterTransition');
afterTransition($el, 'transform', onEndFn, options.time);
//////console.timeEnd('afterTransition');
} 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;
function extendEvent (e) {
var touch = (e.touches || [])[0] || e;
e._x = touch.pageX;
e._y = touch.clientY;
e._now = $.now();
}
function touch ($el, options) {
var el = $el[0],
tail = {},
touchEnabledFLAG,
startEvent,
$target,
controlTouch,
touchFLAG,
targetIsSelectFLAG,
targetIsLinkFlag,
tolerance,
moved;
function onStart (e) {
$target = $(e.target);
tail.checked = targetIsSelectFLAG = targetIsLinkFlag = 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);
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 (!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;
}
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 {
//console.log('onMove e.preventDefault');
stopEvent(e);
(options.onMove || noop).call(el, e, {touch: touchFLAG});
}
if (!moved && Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2)) > tolerance) {
moved = true;
}
tail.checked = tail.checked || xWin || yWin;
}
function onEnd (e) {
////console.time('touch.js onEnd');
(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'});
////console.timeEnd('touch.js onEnd');
}
function onOtherStart () {
if (tail.flow) return;
setTimeout(function () {
tail.flow = true;
}, 10);
}
function onOtherEnd () {
if (!tail.flow) return;
setTimeout(function () {
tail.flow = false;
}, TOUCH_TIMEOUT);
}
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);
addEvent(document, 'touchend', onOtherEnd);
addEvent(document, 'touchcancel', onOtherEnd);
$WINDOW.on('scroll', onOtherEnd);
$el.on('mousedown', onStart);
$DOCUMENT
.on('mousemove', onMove)
.on('mouseup', onEnd);
}
$el.on('click', 'a', 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,
slowFLAG,
controlFLAG,
moved,
tracked;
function startTracking (e, noStop) {
tracked = true;
startCoo = coo = 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;
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 = e._x;
moveTrack.push([e._now, coo]);
moveElPos = startElPos - (startCoo - coo);
edge = findShadowEdge(moveElPos, min, max);
if (moveElPos <= min) {
moveElPos = edgeResistance(moveElPos, min);
} else if (moveElPos >= max) {
moveElPos = edgeResistance(moveElPos, max);
}
if (!tail.noMove) {
$el.css(getTranslate(moveElPos/*, options._001*/));
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) {
////console.time('moveontouch.js onEnd');
if (tail.noSwipe && result.moved) return;
if (!tracked) {
startTracking(result.startEvent, true);
}
//console.log('onEnd');
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}));
}
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 = $(div(wrapClass)),
$stage = $(div(stageClass)).appendTo($wrap),
stage = $stage[0],
$stageShaft = $(div(stageShaftClass)).appendTo($stage),
$stageFrame = $(),
$arrPrev = $(div(arrClass + ' ' + arrPrevClass + buttonAttributes)),
$arrNext = $(div(arrClass + ' ' + arrNextClass + buttonAttributes)),
$arrs = $arrPrev.add($arrNext).appendTo($stage),
$navWrap = $(div(navWrapClass)),
$nav = $(div(navClass)).appendTo($navWrap),
$navShaft = $(div(navShaftClass)).appendTo($nav),
$navFrame,
$navDotFrame = $(),
$navThumbFrame = $(),
stageShaftData = $stageShaft.data(),
navShaftData = $navShaft.data(),
$thumbBorder = $(div(thumbBorderClass)).appendTo($navShaft),
$fullscreenIcon = $(div(fullscreenIconClass + buttonAttributes)),
fullscreenIcon = $fullscreenIcon[0],
$videoPlay = $(div(videoPlayClass)),
$videoClose = $(div(videoCloseClass)).appendTo($stage),
videoClose = $videoClose[0],
spinner,
$spinner = $(div(spinnerClass)),
$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(stageFrameClass));
$wrap[NAV_THUMB_FRAME_KEY] = $(div(navFrameClass + ' ' + navFrameThumbClass + buttonAttributes, div(thumbClass)));
$wrap[NAV_DOT_FRAME_KEY] = $(div(navFrameClass + ' ' + navFrameDotClass + buttonAttributes, div(dotClass)));
toDeactivate[STAGE_FRAME_KEY] = [];
toDeactivate[NAV_THUMB_FRAME_KEY] = [];
toDeactivate[NAV_DOT_FRAME_KEY] = [];
toDetach[STAGE_FRAME_KEY] = {};
$wrap
.addClass(CSS3 ? wrapCss3Class : wrapCss2Class)
.toggleClass(wrapNoControlsClass, !opts.controlsonstart);
fotoramaData.fotorama = this;
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);
}
}
});
}
function allowKey (key) {
return o_keyboard[key] || that.fullScreen;
}
function bindGlobalEvents (FLAG) {
var keydownCommon = 'keydown.' + _fotoramaClass,
localStamp = _fotoramaClass + stamp,
keydownLocal = 'keydown.' + localStamp,
resizeLocal = 'resize.' + localStamp + ' ' + 'orientationchange.' + localStamp;
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.keyCode === 37 && allowKey('left')) || (e.keyCode === 38 && allowKey('up'))) {
index = '<';
} else if ((e.keyCode === 32 && allowKey('space')) || (e.keyCode === 39 && allowKey('right')) || (e.keyCode === 40 && allowKey('down'))) {
index = '>';
} else if (e.keyCode === 36 && allowKey('home')) {
index = '<<';
} else if (e.keyCode === 35 && allowKey('end')) {
index = '>>';
}
}
(catched || index) && stopEvent(e);
index && that.show({index: index, slow: e.altKey, user: true});
});
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
.html('')
.addClass(_fotoramaClass + ' ' + stampClass)
.append($wrap)
.before($style)
.before($anchor);
addInstance(that);
} else {
$wrap.detach();
$style.detach();
$anchor.detach();
$fotorama
.html(fotoramaData.urtext)
.removeClass(stampClass);
hideInstance(that);
}
bindGlobalEvents(FLAG);
appendElements.f = FLAG;
}
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 && !opts.enableifsingleframe) || $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);
}
/**
* Options on the fly
* */
function setOptions () {
that.options = opts = optionsToLowerCase(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);
var classes = {add: [], remove: []};
function addOrRemoveClass (FLAG, value) {
classes[FLAG ? 'add' : 'remove'].push(value);
}
if (size > 1 || opts.enableifsingleframe) {
o_nav = opts.nav;
o_navTop = opts.navposition === 'top';
classes.remove.push(selectClass);
$arrs.toggle(!!opts.arrows);
} else {
o_nav = false;
$arrs.hide();
}
spinnerStop();
spinner = new Spinner($.extend(spinnerDefaults, opts.spinner, spinnerOverride, {direction: o_rtl ? -1 : 1}));
arrsUpdate();
stageWheelUpdate();
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 (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 {
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 !== 'always', wrapToggleArrowsClass);
o_shadows = opts.shadows && !SLOW;
addOrRemoveClass(!o_shadows, wrapNoShadowsClass);
$wrap
.addClass(classes.add.join(' '))
.removeClass(classes.remove.join(' '));
lastOptions = $.extend({}, opts);
}
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 () {
//////console.log('setNavShaftMinMax', measures.nw);
navShaftTouchTail.min = Math.min(0, measures.nw - $navShaft.width());
navShaftTouchTail.max = 0;
$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)) {
////console.log('setMeasures', index, opts.width, opts.height);
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, method, position, again) {
eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) {
if (!$frame) return;
var fullFLAG = that.fullScreen && dataFrame.full && dataFrame.full !== dataFrame.img && !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 ? null : 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;
loadImg([index], type, specialMeasures, method, position, 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 () {
////console.log('loaded: ' + src);
//console.log('$.Fotorama.measures[src]', $.Fotorama.measures[src]);
$.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(imgClass + (fullFLAG ? ' ' + imgFullClass : ''))
.prependTo($frame);
fit($img, ($.isFunction(specialMeasures) ? specialMeasures() : specialMeasures) || measures, method || dataFrame.fit || opts.fit, position || dataFrame.position || opts.position);
$.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') {
//console.log('take from cache: ' + src);
setTimeout(waitAndLoad, 0);
} else {
setTimeout(justWait, 100);
}
})();
}
frameData.state = '';
img.src = src;
});
}
function spinnerSpin ($el) {
$spinner.append(spinner.spin().el).appendTo($el);
}
function spinnerStop () {
$spinner.detach();
spinner && spinner.stop();
}
function updateFotoramaState () {
var $frame = activeFrame[STAGE_FRAME_KEY];
if ($frame && !$frame.data().state) {
spinnerSpin($frame);
$frame.on('f:load f:error', function () {
$frame.off('f:load f:error');
spinnerStop();
});
}
}
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];
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);
}
dataFrame.caption && $(div(captionClass, div(captionWrapClass, dataFrame.caption))).appendTo($frame);
dataFrame.video && $frame
.addClass(stageFrameVideoClass)
.append($videoPlay.clone());
// This solves tabbing problems
addFocus(frame, function () {
setTimeout(function () {
lockScroll($stage);
}, 0);
clickToShow({index: frameData.eq, user: true});
});
$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, method, position) {
return $img && $img.length && fit($img, measuresToFit, method, position);
}
function stageFramePosition (indexes) {
eachIndex(indexes, 'stage', function (i, index, dataFrame, $frame, key, frameData) {
if (!$frame) return;
var normalizedIndex = normalizeIndex(index),
method = dataFrame.fit || opts.fit,
position = dataFrame.position || opts.position;
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, method, position);
callFit(frameData.$full, measures, method, position);
});
}
function thumbsDraw (pos, loadFLAG) {
if (o_nav !== 'thumbs' || isNaN(pos)) return;
var leftLimit = -pos,
rightLimit = -pos + measures.nw;
$navThumbFrame.each(function () {
var $this = $(this),
thisData = $this.data(),
eq = thisData.eq,
getSpecialMeasures = function () {
return {
h: o_thumbSide2,
w: thisData.w
}
},
specialMeasures = getSpecialMeasures(),
dataFrame = data[eq] || {},
method = dataFrame.thumbfit || opts.thumbfit,
position = dataFrame.thumbposition || opts.thumbposition;
specialMeasures.w = thisData.w;
if (thisData.l + thisData.w < leftLimit
|| thisData.l > rightLimit
|| callFit(thisData.$img, specialMeasures, method, position)) return;
loadFLAG && loadImg([eq], 'navThumb', getSpecialMeasures, method, position);
});
}
function frameAppend ($frames, $shaft, type) {
if (!frameAppend[type]) {
var thumbsFLAG = type === 'nav' && o_navThumbs,
left = 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 () {
if (!thumbsFLAG) return;
var $this = $(this),
frameData = $this.data(),
thumbwidth = Math.round(o_thumbSide2 * frameData.data.thumbratio) || o_thumbSide;
frameData.l = left;
frameData.w = thumbwidth;
$this.css({width: thumbwidth});
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));
$arrNext
.toggleClass(arrDisabledClass, disableNext)
.attr(disableAttr(disableNext));
}
function stageWheelUpdate () {
if (stageWheelTail.ok) {
stageWheelTail.prevent = {'<': disableDirrection(0), '>': disableDirrection(1)};
}
}
function getNavFrameBounds ($navFrame) {
var navFrameData = $navFrame.data(),
left,
width;
if (o_navThumbs) {
left = navFrameData.l;
width = navFrameData.w;
} else {
left = $navFrame.position().left;
width = $navFrame.width();
}
return {
c: left + width / 2,
min: -left + opts.thumbmargin * 10,
max: -left + measures.w - width - opts.thumbmargin * 10
};
}
function slideThumbBorder (time) {
var navFrameData = activeFrame[navFrameKey].data();
slide($thumbBorder, {
time: time * 1.2,
pos: navFrameData.l,
width: navFrameData.w - opts.thumbborderwidth * 2
});
}
function slideNavShaft (options) {
//console.log('slideNavShaft', options.guessIndex, options.keep, slideNavShaft.l);
var $guessNavFrame = data[options.guessIndex][navFrameKey];
if ($guessNavFrame) {
var overflowFLAG = navShaftTouchTail.min !== navShaftTouchTail.max,
minMax = options.minMax || overflowFLAG && getNavFrameBounds(activeFrame[navFrameKey]),
l = overflowFLAG && (options.keep && slideNavShaft.l ? slideNavShaft.l : minMaxLimit((options.coo || measures.nw / 2) - getNavFrameBounds($guessNavFrame).c, minMax.min, minMax.max)),
pos = overflowFLAG && minMaxLimit(l, navShaftTouchTail.min, navShaftTouchTail.max),
time = options.time * 1.1;
slide($navShaft, {
time: time,
pos: pos || 0,
onEnd: function () {
thumbsDraw(pos, true);
}
});
//if (time) thumbsDraw(pos);
setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max));
slideNavShaft.l = l;
}
}
function navUpdate () {
deactivateFrames(navFrameKey);
toDeactivate[navFrameKey].push(activeFrame[navFrameKey].addClass(activeClass));
}
function deactivateFrames (key) {
var _toDeactivate = toDeactivate[key];
while (_toDeactivate.length) {
_toDeactivate.shift().removeClass(activeClass);
}
}
function detachFrames (key) {
var _toDetach = toDetach[key];
////console.log('_toDetach', _toDetach);
////console.log('activeIndexes', activeIndexes);
$.each(activeIndexes, function (i, index) {
delete _toDetach[normalizeIndex(index)];
});
$.each(_toDetach, function (index, $frame) {
delete _toDetach[index];
////console.log('Detach', 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));
skipOnEnd || that.show.onEnd(true);
stop($stageShaft, 0, true);
detachFrames(STAGE_FRAME_KEY);
stageFramePosition(activeIndexes);
setStageShaftMinmaxAndSnap();
setNavShaftMinMax();
}
}
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);
////console.timeEnd('onTouchEnd');
}
function releaseAutoplay () {
//console.log('releaseAutoplay');
pausedAutoplayFLAG = !!($videoPlaying || stoppedAutoplayFLAG);
}
function changeAutoplay () {
//console.log('changeAutoplay');
clearTimeout(changeAutoplay.t);
waitFor.stop(changeAutoplay.w);
if (!opts.autoplay || pausedAutoplayFLAG) {
if (that.autoplay) {
that.autoplay = false;
triggerEvent('stopautoplay');
}
return;
}
//console.log('changeAutoplay continue');
if (!that.autoplay) {
that.autoplay = true;
triggerEvent('startautoplay');
}
var _activeIndex = activeIndex;
var frameData = activeFrame[STAGE_FRAME_KEY].data();
changeAutoplay.w = waitFor(function () {
//console.log('wait for the state of the current frame');
return frameData.state || _activeIndex !== activeIndex;
}, function () {
//console.log('the current frame is ready');
changeAutoplay.t = setTimeout(function () {
//console.log('changeAutoplay.t setTimeout', pausedAutoplayFLAG, _activeIndex !== activeIndex);
if (pausedAutoplayFLAG || _activeIndex !== activeIndex) return;
var _nextAutoplayIndex = nextAutoplayIndex,
nextFrameData = data[_nextAutoplayIndex][STAGE_FRAME_KEY].data();
changeAutoplay.w = waitFor(function () {
//console.log('wait for the state of the next frame');
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.show = function (options) {
//console.log('that.show');
////console.time('that.show prepare');
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) ? getIndexFromHash(index, data, true) : index;
index = typeof index === 'undefined' ? activeIndex || 0 : 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;
var diffIndex = Math.abs(lastActiveIndex - dirtyIndex),
time = getNumber(options.time, function () {
return Math.min(o_transitionDuration * (1 + (diffIndex - 1) / 12), o_transitionDuration * 2);
}),
overPos = options.overPos;
if (options.slow) time *= 10;
var _activeFrame = activeFrame;
that.activeFrame = activeFrame = data[activeIndex];
////console.timeEnd('that.show prepare');
var silent = _activeFrame === activeFrame && !options.user;
//setTimeout(function () {
////console.time('unloadVideo');
unloadVideo($videoPlaying, activeFrame.i !== data[normalizeIndex(repositionIndex)].i);
////console.timeEnd('unloadVideo');
////console.time('frameDraw');
frameDraw(activeIndexes, 'stage');
////console.timeEnd('frameDraw');
////console.time('stageFramePosition');
stageFramePosition(SLOW ? [dirtyIndex] : [dirtyIndex, getPrevIndex(dirtyIndex), getNextIndex(dirtyIndex)]);
////console.timeEnd('stageFramePosition');
////console.time('updateTouchTails');
updateTouchTails('go', true);
////console.timeEnd('updateTouchTails');
////console.time('triggerEvent');
silent || triggerEvent('show', {
user: options.user,
time: time
});
////console.timeEnd('triggerEvent');
//}, 0);
////console.time('bind onEnd');
pausedAutoplayFLAG = true;
var onEnd = that.show.onEnd = function (skipReposition) {
if (onEnd.ok) return;
onEnd.ok = true;
skipReposition || stageShaftReposition(true);
if (!silent) {
triggerEvent('showend', {
user: options.user
});
}
//console.log('o_transition', o_transition);
if (!skipReposition && o_transition && o_transition !== opts.transition) {
//console.log('set transition back to: ' + o_transition);
that.setOptions({transition: o_transition});
o_transition = false;
return;
}
updateFotoramaState();
loadImg(activeIndexes, 'stage');
updateTouchTails('go', false);
stageWheelUpdate();
stageCursor();
releaseAutoplay();
changeAutoplay();
};
////console.timeEnd('bind onEnd');
if (!o_fade) {
////console.time('slide');
slide($stageShaft, {
pos: -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex),
overPos: overPos,
time: time,
onEnd: onEnd/*,
_001: true*/
});
////console.timeEnd('slide');
} else {
var $activeFrame = activeFrame[STAGE_FRAME_KEY],
$prevActiveFrame = activeIndex !== lastActiveIndex ? data[lastActiveIndex][STAGE_FRAME_KEY] : null;
fade($activeFrame, $prevActiveFrame, $stageFrame, {
time: time,
method: opts.transition,
onEnd: onEnd
}, fadeStack);
}
////console.time('arrsUpdate');
arrsUpdate();
////console.timeEnd('arrsUpdate');
if (o_nav) {
////console.time('navUpdate');
navUpdate();
////console.timeEnd('navUpdate');
////console.time('slideNavShaft');
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});
////console.timeEnd('slideNavShaft');
////console.time('slideThumbBorder');
if (o_navThumbs) slideThumbBorder(time);
////console.timeEnd('slideThumbBorder');
}
////console.time('that.show end');
showedFLAG = typeof lastActiveIndex !== 'undefined' && lastActiveIndex !== activeIndex;
lastActiveIndex = activeIndex;
opts.hash && showedFLAG && !that.eq && setHash(activeFrame.id || activeIndex + 1);
////console.timeEnd('that.show end');
////console.timeEnd('that.show');
return this;
};
that.requestFullScreen = function () {
if (o_allowFullScreen && !that.fullScreen) {
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);
}
that.resize();
loadImg(activeIndexes, 'stage');
updateFotoramaState();
triggerEvent('fullscreenenter');
}
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']();
};
addEvent(document, fullScreenApi.event, function () {
if (data && !fullScreenApi.is() && !$videoPlaying) {
cancelFullScreen();
}
});
that.resize = function (options) {
if (!data) return this;
var time = arguments[1] || 0,
setFLAG = arguments[2];
extendMeasures(!that.fullScreen ? optionsToLowerCase(options) : {width: '100%', maxwidth: null, minwidth: null, height: '100%', 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
.addClass(wrapOnlyActiveClass)
.css({width: width, minWidth: measures.minwidth || 0, maxWidth: measures.maxwidth || MAX_WIDTH});
width = measures.W = measures.w = $wrap.width();
measures.nw = o_nav && numberFromWhatever(opts.navwidth, width) || width;
if (opts.glimpse) {
// Glimpse
measures.w -= Math.round((numberFromWhatever(opts.glimpse, width) || 0) * 2);
}
$stageShaft.css({width: measures.w, marginLeft: (measures.W - measures.w) / 2});
////console.log('measures.W', measures.W);
////console.log('measures.w', measures.w);
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
.stop()
.animate({width: width, height: height}, time, function () {
$wrap.removeClass(wrapOnlyActiveClass);
});
stageShaftReposition();
if (o_nav) {
$nav
.stop()
.animate({width: measures.nw}, time);
slideNavShaft({guessIndex: activeIndex, time: time, keep: true});
if (o_navThumbs && frameAppend.nav) slideThumbBorder(time);
}
measuresSetFLAG = setFLAG || true;
ready();
}
}
stageLeft = $stage.offset().left;
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) {
////console.time('setShadow');
if (o_shadows) {
$el.removeClass(shadowsLeftClass + ' ' + shadowsRightClass);
edge && !$videoPlaying && $el.addClass(edge.replace(/^|\s/g, ' ' + shadowsClass + '--'));
}
////console.timeEnd('setShadow');
}
that.destroy = function () {
that.cancelFullScreen();
that.stopAutoplay();
data = that.data = null;
appendElements();
activeIndexes = [];
detachFrames(STAGE_FRAME_KEY);
reset.ok = false;
return this;
};
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 || $($.Fotorama.jst.video(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;
};
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) {
clearTimeout(clickToShow.t);
if (opts.clicktransition && opts.clicktransition !== opts.transition) {
//console.log('change transition to: ' + opts.clicktransition);
// this timeout is for yield events flow
setTimeout(function () {
// save original transition for later
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);
}
}
function onStageTap (e, toggleControlsFLAG) {
////console.time('onStageTap');
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 (toggleControlsFLAG) {
toggleControlsClass();
} else if (opts.click) {
clickToShow({index: e.shiftKey || getDirectionSign(getDirection(e._x)), slow: e.altKey, user: true});
}
}
////console.timeEnd('onStageTap');
}
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) {
////console.time('stageShaftTouchTail.onEnd');
setShadow($stage);
////console.log('result', result);
var toggleControlsFLAG = (MS_POINTER && !hoverFLAG || result.touch) && opts.arrows && opts.arrows !== 'always';
if (result.moved || (toggleControlsFLAG && result.pos !== result.newPos && !result.control)) {
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);
}
////console.timeEnd('stageShaftTouchTail.onEnd');
},
// getPos: function () {
// return -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex);
// },
//_001: true,
timeLow: 1,
timeHigh: 1,
friction: 2,
select: '.' + selectClass + ', .' + selectClass + ' *',
$wrap: $stage
});
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);
}
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,
onEnd: onEnd
});
thumbsDraw(result.newPos);
o_shadows && setShadow($nav, findShadowEdge(result.newPos, navShaftTouchTail.min, navShaftTouchTail.max));
} else {
onEnd();
}
},
timeLow: .5,
timeHigh: 2,
friction: 5,
$wrap: $nav
});
stageWheelTail = wheel($stage, {
shift: true,
onEnd: function (e, direction) {
////console.log('wheel $stage onEnd', direction);
onTouchStart();
onTouchEnd();
that.show({index: direction, slow: e.altKey})
}
});
navWheelTail = wheel($nav, {
onEnd: function (e, direction) {
////console.log('wheel $nav onEnd', direction);
onTouchStart();
onTouchEnd();
var newPos = stop($navShaft) + direction * .25;
$navShaft.css(getTranslate(minMaxLimit(newPos, navShaftTouchTail.min, navShaftTouchTail.max)));
o_shadows && setShadow($nav, findShadowEdge(newPos, navShaftTouchTail.min, navShaftTouchTail.max));
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;
clickToShow({index: index, slow: e.altKey, user: true, coo: e._x - $nav.offset().left});
}
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
});
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, that.toggleFullScreen);
addFocusOnControls(fullscreenIcon);
function reset () {
setData();
setOptions();
if (!reset.i) {
reset.i = true;
// Only once
var _startindex = opts.startindex;
if (_startindex || opts.hash && location.hash) {
startIndex = getIndexFromHash(_startindex || location.hash.replace(/^#/, ''), data, that.index === 0 || _startindex, _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 = [];
detachFrames(STAGE_FRAME_KEY);
reset.ok = true;
that.show({index: activeIndex, time: 0});
that.resize();
} else {
that.destroy();
}
}
function changeToRtl () {
////console.log('changeToRtl');
if (!changeToRtl.f === o_rtl) {
changeToRtl.f = o_rtl;
activeIndex = size - 1 - activeIndex;
////console.log('changeToRtl execute, activeIndex is', 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 = true;
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,
/* Priority for options:
* 1. <div data-loop="true"></div>
* 2. $('div').fotorama({loop: false})
* 3. Defaults */
$.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.style = function(v) {
var __t, __p = '', __e = _.escape;
__p += '.fotorama' +
((__t = ( v.s )) == null ? '' : __t) +
' .fotorama__nav--thumbs .fotorama__nav__frame{\npadding:' +
((__t = ( v.m )) == null ? '' : __t) +
'px;\nheight:' +
((__t = ( v.h )) == null ? '' : __t) +
'px}\n.fotorama' +
((__t = ( v.s )) == null ? '' : __t) +
' .fotorama__thumb-border{\nheight:' +
((__t = ( v.h - v.b * (v.q ? 0 : 2) )) == null ? '' : __t) +
'px;\nborder-width:' +
((__t = ( v.b )) == null ? '' : __t) +
'px;\nmargin-top:' +
((__t = ( v.m )) == null ? '' : __t) +
'px}';
return __p
};
$.Fotorama.jst.video = function(v) {
var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
function print() { __p += __j.call(arguments, '') }
__p += '<div class="fotorama__video"><iframe src="';
print((v.type == 'youtube' ? v.p + 'youtube.com/embed/' + v.id +'?autoplay=1' : v.type == 'vimeo' ? v.p + 'player.vimeo.com/video/' + v.id + '?autoplay=1&badge=0' : v.id) + (v.s && v.type != 'custom' ? '&' + v.s : '')) ;
__p += '" frameborder="0" allowfullscreen></iframe></div>\n';
return __p
};
$(function () {
$('.' + _fotoramaClass + ':not([data-auto="false"])').fotorama();
});
})(window, document, location, typeof jQuery !== 'undefined' && jQuery);