fotoramajs 4.6.3 → 4.6.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,2 +1,3705 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>D3318AE085B3BFAC</RequestId><HostId>h1ELuAQia3cs/P/e5NF+jhW6sDfJnNGhLs9MUZCDNMuxh41QuFtz9HebbmXVnJc4</HostId></Error>
1
+ /*!
2
+ * Fotorama 4.6.3 | http://fotorama.io/license/
3
+ */
4
+ fotoramaVersion = '4.6.3';
5
+ (function (window, document, location, $, undefined) {
6
+ "use strict";
7
+ var _fotoramaClass = 'fotorama',
8
+ _fullscreenClass = 'fullscreen',
9
+
10
+ wrapClass = _fotoramaClass + '__wrap',
11
+ wrapCss2Class = wrapClass + '--css2',
12
+ wrapCss3Class = wrapClass + '--css3',
13
+ wrapVideoClass = wrapClass + '--video',
14
+ wrapFadeClass = wrapClass + '--fade',
15
+ wrapSlideClass = wrapClass + '--slide',
16
+ wrapNoControlsClass = wrapClass + '--no-controls',
17
+ wrapNoShadowsClass = wrapClass + '--no-shadows',
18
+ wrapPanYClass = wrapClass + '--pan-y',
19
+ wrapRtlClass = wrapClass + '--rtl',
20
+ wrapOnlyActiveClass = wrapClass + '--only-active',
21
+ wrapNoCaptionsClass = wrapClass + '--no-captions',
22
+ wrapToggleArrowsClass = wrapClass + '--toggle-arrows',
23
+
24
+ stageClass = _fotoramaClass + '__stage',
25
+ stageFrameClass = stageClass + '__frame',
26
+ stageFrameVideoClass = stageFrameClass + '--video',
27
+ stageShaftClass = stageClass + '__shaft',
28
+
29
+ grabClass = _fotoramaClass + '__grab',
30
+ pointerClass = _fotoramaClass + '__pointer',
31
+
32
+ arrClass = _fotoramaClass + '__arr',
33
+ arrDisabledClass = arrClass + '--disabled',
34
+ arrPrevClass = arrClass + '--prev',
35
+ arrNextClass = arrClass + '--next',
36
+ arrArrClass = arrClass + '__arr',
37
+
38
+ navClass = _fotoramaClass + '__nav',
39
+ navWrapClass = navClass + '-wrap',
40
+ navShaftClass = navClass + '__shaft',
41
+ navDotsClass = navClass + '--dots',
42
+ navThumbsClass = navClass + '--thumbs',
43
+ navFrameClass = navClass + '__frame',
44
+ navFrameDotClass = navFrameClass + '--dot',
45
+ navFrameThumbClass = navFrameClass + '--thumb',
46
+
47
+ fadeClass = _fotoramaClass + '__fade',
48
+ fadeFrontClass = fadeClass + '-front',
49
+ fadeRearClass = fadeClass + '-rear',
50
+
51
+ shadowClass = _fotoramaClass + '__shadow',
52
+ shadowsClass = shadowClass + 's',
53
+ shadowsLeftClass = shadowsClass + '--left',
54
+ shadowsRightClass = shadowsClass + '--right',
55
+
56
+ activeClass = _fotoramaClass + '__active',
57
+ selectClass = _fotoramaClass + '__select',
58
+
59
+ hiddenClass = _fotoramaClass + '--hidden',
60
+
61
+ fullscreenClass = _fotoramaClass + '--fullscreen',
62
+ fullscreenIconClass = _fotoramaClass + '__fullscreen-icon',
63
+
64
+ errorClass = _fotoramaClass + '__error',
65
+ loadingClass = _fotoramaClass + '__loading',
66
+ loadedClass = _fotoramaClass + '__loaded',
67
+ loadedFullClass = loadedClass + '--full',
68
+ loadedImgClass = loadedClass + '--img',
69
+
70
+ grabbingClass = _fotoramaClass + '__grabbing',
71
+
72
+ imgClass = _fotoramaClass + '__img',
73
+ imgFullClass = imgClass + '--full',
74
+
75
+ dotClass = _fotoramaClass + '__dot',
76
+ thumbClass = _fotoramaClass + '__thumb',
77
+ thumbBorderClass = thumbClass + '-border',
78
+
79
+ htmlClass = _fotoramaClass + '__html',
80
+
81
+ videoClass = _fotoramaClass + '__video',
82
+ videoPlayClass = videoClass + '-play',
83
+ videoCloseClass = videoClass + '-close',
84
+
85
+ captionClass = _fotoramaClass + '__caption',
86
+ captionWrapClass = _fotoramaClass + '__caption__wrap',
87
+
88
+ spinnerClass = _fotoramaClass + '__spinner',
89
+
90
+ buttonAttributes = '" tabindex="0" role="button';
91
+ var JQUERY_VERSION = $ && $.fn.jquery.split('.');
92
+
93
+ if (!JQUERY_VERSION
94
+ || JQUERY_VERSION[0] < 1
95
+ || (JQUERY_VERSION[0] == 1 && JQUERY_VERSION[1] < 8)) {
96
+ throw 'Fotorama requires jQuery 1.8 or later and will not run without it.';
97
+ }
98
+ // My Underscore :-)
99
+ var _ = {};
100
+ /* Modernizr 2.6.2 (Custom Build) | MIT & BSD
101
+ * Build: http://modernizr.com/download/#-csstransforms3d-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes
102
+ */
103
+
104
+ var Modernizr = (function (window, document, undefined) {
105
+
106
+ var version = '2.6.2',
107
+
108
+ Modernizr = {},
109
+
110
+ docElement = document.documentElement,
111
+
112
+ mod = 'modernizr',
113
+ modElem = document.createElement(mod),
114
+ mStyle = modElem.style,
115
+
116
+ inputElem,
117
+
118
+ toString = {}.toString,
119
+
120
+ prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
121
+
122
+ omPrefixes = 'Webkit Moz O ms',
123
+
124
+ cssomPrefixes = omPrefixes.split(' '),
125
+
126
+ domPrefixes = omPrefixes.toLowerCase().split(' '),
127
+
128
+ tests = {},
129
+ inputs = {},
130
+ attrs = {},
131
+
132
+ classes = [],
133
+
134
+ slice = classes.slice,
135
+
136
+ featureName,
137
+
138
+ injectElementWithStyles = function (rule, callback, nodes, testnames) {
139
+
140
+ var style, ret, node, docOverflow,
141
+ div = document.createElement('div'),
142
+ body = document.body,
143
+ fakeBody = body || document.createElement('body');
144
+
145
+ if (parseInt(nodes, 10)) {
146
+ while (nodes--) {
147
+ node = document.createElement('div');
148
+ node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
149
+ div.appendChild(node);
150
+ }
151
+ }
152
+
153
+ style = ['&#173;', '<style id="s', mod, '">', rule, '</style>'].join('');
154
+ div.id = mod;
155
+ (body ? div : fakeBody).innerHTML += style;
156
+ fakeBody.appendChild(div);
157
+ if (!body) {
158
+ fakeBody.style.background = '';
159
+ fakeBody.style.overflow = 'hidden';
160
+ docOverflow = docElement.style.overflow;
161
+ docElement.style.overflow = 'hidden';
162
+ docElement.appendChild(fakeBody);
163
+ }
164
+
165
+ ret = callback(div, rule);
166
+ if (!body) {
167
+ fakeBody.parentNode.removeChild(fakeBody);
168
+ docElement.style.overflow = docOverflow;
169
+ } else {
170
+ div.parentNode.removeChild(div);
171
+ }
172
+
173
+ return !!ret;
174
+
175
+ },
176
+ _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
177
+
178
+ if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) {
179
+ hasOwnProp = function (object, property) {
180
+ return _hasOwnProperty.call(object, property);
181
+ };
182
+ }
183
+ else {
184
+ hasOwnProp = function (object, property) {
185
+ return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
186
+ };
187
+ }
188
+
189
+
190
+ if (!Function.prototype.bind) {
191
+ Function.prototype.bind = function bind (that) {
192
+
193
+ var target = this;
194
+
195
+ if (typeof target != "function") {
196
+ throw new TypeError();
197
+ }
198
+
199
+ var args = slice.call(arguments, 1),
200
+ bound = function () {
201
+
202
+ if (this instanceof bound) {
203
+
204
+ var F = function () {
205
+ };
206
+ F.prototype = target.prototype;
207
+ var self = new F();
208
+
209
+ var result = target.apply(
210
+ self,
211
+ args.concat(slice.call(arguments))
212
+ );
213
+ if (Object(result) === result) {
214
+ return result;
215
+ }
216
+ return self;
217
+
218
+ } else {
219
+
220
+ return target.apply(
221
+ that,
222
+ args.concat(slice.call(arguments))
223
+ );
224
+
225
+ }
226
+
227
+ };
228
+
229
+ return bound;
230
+ };
231
+ }
232
+
233
+ function setCss (str) {
234
+ mStyle.cssText = str;
235
+ }
236
+
237
+ function setCssAll (str1, str2) {
238
+ return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
239
+ }
240
+
241
+ function is (obj, type) {
242
+ return typeof obj === type;
243
+ }
244
+
245
+ function contains (str, substr) {
246
+ return !!~('' + str).indexOf(substr);
247
+ }
248
+
249
+ function testProps (props, prefixed) {
250
+ for (var i in props) {
251
+ var prop = props[i];
252
+ if (!contains(prop, "-") && mStyle[prop] !== undefined) {
253
+ return prefixed == 'pfx' ? prop : true;
254
+ }
255
+ }
256
+ return false;
257
+ }
258
+
259
+ function testDOMProps (props, obj, elem) {
260
+ for (var i in props) {
261
+ var item = obj[props[i]];
262
+ if (item !== undefined) {
263
+
264
+ if (elem === false) return props[i];
265
+
266
+ if (is(item, 'function')) {
267
+ return item.bind(elem || obj);
268
+ }
269
+
270
+ return item;
271
+ }
272
+ }
273
+ return false;
274
+ }
275
+
276
+ function testPropsAll (prop, prefixed, elem) {
277
+
278
+ var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
279
+ props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
280
+
281
+ if (is(prefixed, "string") || is(prefixed, "undefined")) {
282
+ return testProps(props, prefixed);
283
+
284
+ } else {
285
+ props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
286
+ return testDOMProps(props, prefixed, elem);
287
+ }
288
+ }
289
+
290
+ tests['csstransforms3d'] = function () {
291
+
292
+ var ret = !!testPropsAll('perspective');
293
+
294
+ // Chrome fails that test, ignore
295
+ // if (ret && 'webkitPerspective' in docElement.style) {
296
+ //
297
+ // injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function (node, rule) {
298
+ // ret = node.offsetLeft === 9 && node.offsetHeight === 3;
299
+ // });
300
+ // }
301
+ return ret;
302
+ };
303
+
304
+ for (var feature in tests) {
305
+ if (hasOwnProp(tests, feature)) {
306
+ featureName = feature.toLowerCase();
307
+ Modernizr[featureName] = tests[feature]();
308
+
309
+ classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
310
+ }
311
+ }
312
+
313
+ Modernizr.addTest = function (feature, test) {
314
+ if (typeof feature == 'object') {
315
+ for (var key in feature) {
316
+ if (hasOwnProp(feature, key)) {
317
+ Modernizr.addTest(key, feature[ key ]);
318
+ }
319
+ }
320
+ } else {
321
+
322
+ feature = feature.toLowerCase();
323
+
324
+ if (Modernizr[feature] !== undefined) {
325
+ return Modernizr;
326
+ }
327
+
328
+ test = typeof test == 'function' ? test() : test;
329
+
330
+ if (typeof enableClasses !== "undefined" && enableClasses) {
331
+ docElement.className += ' ' + (test ? '' : 'no-') + feature;
332
+ }
333
+ Modernizr[feature] = test;
334
+
335
+ }
336
+
337
+ return Modernizr;
338
+ };
339
+
340
+
341
+ setCss('');
342
+ modElem = inputElem = null;
343
+
344
+
345
+ Modernizr._version = version;
346
+
347
+ Modernizr._prefixes = prefixes;
348
+ Modernizr._domPrefixes = domPrefixes;
349
+ Modernizr._cssomPrefixes = cssomPrefixes;
350
+
351
+ Modernizr.testProp = function (prop) {
352
+ return testProps([prop]);
353
+ };
354
+
355
+ Modernizr.testAllProps = testPropsAll;
356
+
357
+ Modernizr.testStyles = injectElementWithStyles;
358
+ Modernizr.prefixed = function (prop, obj, elem) {
359
+ if (!obj) {
360
+ return testPropsAll(prop, 'pfx');
361
+ } else {
362
+ return testPropsAll(prop, obj, elem);
363
+ }
364
+ };
365
+
366
+ return Modernizr;
367
+ })(window, document);
368
+ var fullScreenApi = {
369
+ ok: false,
370
+ is: function () {
371
+ return false;
372
+ },
373
+ request: function () {
374
+ },
375
+ cancel: function () {
376
+ },
377
+ event: '',
378
+ prefix: ''
379
+ },
380
+ browserPrefixes = 'webkit moz o ms khtml'.split(' ');
381
+
382
+ // check for native support
383
+ if (typeof document.cancelFullScreen != 'undefined') {
384
+ fullScreenApi.ok = true;
385
+ } else {
386
+ // check for fullscreen support by vendor prefix
387
+ for (var i = 0, il = browserPrefixes.length; i < il; i++) {
388
+ fullScreenApi.prefix = browserPrefixes[i];
389
+ if (typeof document[fullScreenApi.prefix + 'CancelFullScreen' ] != 'undefined') {
390
+ fullScreenApi.ok = true;
391
+ break;
392
+ }
393
+ }
394
+ }
395
+
396
+ // update methods to do something useful
397
+ if (fullScreenApi.ok) {
398
+ fullScreenApi.event = fullScreenApi.prefix + 'fullscreenchange';
399
+ fullScreenApi.is = function () {
400
+ switch (this.prefix) {
401
+ case '':
402
+ return document.fullScreen;
403
+ case 'webkit':
404
+ return document.webkitIsFullScreen;
405
+ default:
406
+ return document[this.prefix + 'FullScreen'];
407
+ }
408
+ };
409
+ fullScreenApi.request = function (el) {
410
+ return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
411
+ };
412
+ fullScreenApi.cancel = function (el) {
413
+ return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
414
+ };
415
+ }
416
+ //fgnass.github.com/spin.js#v1.3.2
417
+
418
+ /**
419
+ * Copyright (c) 2011-2013 Felix Gnass
420
+ * Licensed under the MIT license
421
+ */
422
+
423
+ var Spinner,
424
+ spinnerDefaults = {
425
+ lines: 12, // The number of lines to draw
426
+ length: 5, // The length of each line
427
+ width: 2, // The line thickness
428
+ radius: 7, // The radius of the inner circle
429
+ corners: 1, // Corner roundness (0..1)
430
+ rotate: 15, // The rotation offset
431
+ color: 'rgba(128, 128, 128, .75)',
432
+ hwaccel: true
433
+ },
434
+ spinnerOverride = {
435
+ top: 'auto',
436
+ left: 'auto',
437
+ className: ''
438
+ };
439
+
440
+ (function(root, factory) {
441
+
442
+ /* CommonJS */
443
+ //if (typeof exports == 'object') module.exports = factory()
444
+
445
+ /* AMD module */
446
+ //else if (typeof define == 'function' && define.amd) define(factory)
447
+
448
+ /* Browser global */
449
+ //else root.Spinner = factory()
450
+
451
+ Spinner = factory();
452
+ }
453
+ (this, function() {
454
+ "use strict";
455
+
456
+ var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */
457
+ , animations = {} /* Animation rules keyed by their name */
458
+ , useCssAnimations /* Whether to use CSS animations or setTimeout */
459
+
460
+ /**
461
+ * Utility function to create elements. If no tag name is given,
462
+ * a DIV is created. Optionally properties can be passed.
463
+ */
464
+ function createEl(tag, prop) {
465
+ var el = document.createElement(tag || 'div')
466
+ , n
467
+
468
+ for(n in prop) el[n] = prop[n]
469
+ return el
470
+ }
471
+
472
+ /**
473
+ * Appends children and returns the parent.
474
+ */
475
+ function ins(parent /* child1, child2, ...*/) {
476
+ for (var i=1, n=arguments.length; i<n; i++)
477
+ parent.appendChild(arguments[i])
478
+
479
+ return parent
480
+ }
481
+
482
+ /**
483
+ * Insert a new stylesheet to hold the @keyframe or VML rules.
484
+ */
485
+ var sheet = (function() {
486
+ var el = createEl('style', {type : 'text/css'})
487
+ ins(document.getElementsByTagName('head')[0], el)
488
+ return el.sheet || el.styleSheet
489
+ }())
490
+
491
+ /**
492
+ * Creates an opacity keyframe animation rule and returns its name.
493
+ * Since most mobile Webkits have timing issues with animation-delay,
494
+ * we create separate rules for each line/segment.
495
+ */
496
+ function addAnimation(alpha, trail, i, lines) {
497
+ var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-')
498
+ , start = 0.01 + i/lines * 100
499
+ , z = Math.max(1 - (1-alpha) / trail * (100-start), alpha)
500
+ , prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase()
501
+ , pre = prefix && '-' + prefix + '-' || ''
502
+
503
+ if (!animations[name]) {
504
+ sheet.insertRule(
505
+ '@' + pre + 'keyframes ' + name + '{' +
506
+ '0%{opacity:' + z + '}' +
507
+ start + '%{opacity:' + alpha + '}' +
508
+ (start+0.01) + '%{opacity:1}' +
509
+ (start+trail) % 100 + '%{opacity:' + alpha + '}' +
510
+ '100%{opacity:' + z + '}' +
511
+ '}', sheet.cssRules.length)
512
+
513
+ animations[name] = 1
514
+ }
515
+
516
+ return name
517
+ }
518
+
519
+ /**
520
+ * Tries various vendor prefixes and returns the first supported property.
521
+ */
522
+ function vendor(el, prop) {
523
+ var s = el.style
524
+ , pp
525
+ , i
526
+
527
+ prop = prop.charAt(0).toUpperCase() + prop.slice(1)
528
+ for(i=0; i<prefixes.length; i++) {
529
+ pp = prefixes[i]+prop
530
+ if(s[pp] !== undefined) return pp
531
+ }
532
+ if(s[prop] !== undefined) return prop
533
+ }
534
+
535
+ /**
536
+ * Sets multiple style properties at once.
537
+ */
538
+ function css(el, prop) {
539
+ for (var n in prop)
540
+ el.style[vendor(el, n)||n] = prop[n]
541
+
542
+ return el
543
+ }
544
+
545
+ /**
546
+ * Fills in default values.
547
+ */
548
+ function merge(obj) {
549
+ for (var i=1; i < arguments.length; i++) {
550
+ var def = arguments[i]
551
+ for (var n in def)
552
+ if (obj[n] === undefined) obj[n] = def[n]
553
+ }
554
+ return obj
555
+ }
556
+
557
+ /**
558
+ * Returns the absolute page-offset of the given element.
559
+ */
560
+ function pos(el) {
561
+ var o = { x:el.offsetLeft, y:el.offsetTop }
562
+ while((el = el.offsetParent))
563
+ o.x+=el.offsetLeft, o.y+=el.offsetTop
564
+
565
+ return o
566
+ }
567
+
568
+ /**
569
+ * Returns the line color from the given string or array.
570
+ */
571
+ function getColor(color, idx) {
572
+ return typeof color == 'string' ? color : color[idx % color.length]
573
+ }
574
+
575
+ // Built-in defaults
576
+
577
+ var defaults = {
578
+ lines: 12, // The number of lines to draw
579
+ length: 7, // The length of each line
580
+ width: 5, // The line thickness
581
+ radius: 10, // The radius of the inner circle
582
+ rotate: 0, // Rotation offset
583
+ corners: 1, // Roundness (0..1)
584
+ color: '#000', // #rgb or #rrggbb
585
+ direction: 1, // 1: clockwise, -1: counterclockwise
586
+ speed: 1, // Rounds per second
587
+ trail: 100, // Afterglow percentage
588
+ opacity: 1/4, // Opacity of the lines
589
+ fps: 20, // Frames per second when using setTimeout()
590
+ zIndex: 2e9, // Use a high z-index by default
591
+ className: 'spinner', // CSS class to assign to the element
592
+ top: 'auto', // center vertically
593
+ left: 'auto', // center horizontally
594
+ position: 'relative' // element position
595
+ }
596
+
597
+ /** The constructor */
598
+ function Spinner(o) {
599
+ if (typeof this == 'undefined') return new Spinner(o)
600
+ this.opts = merge(o || {}, Spinner.defaults, defaults)
601
+ }
602
+
603
+ // Global defaults that override the built-ins:
604
+ Spinner.defaults = {}
605
+
606
+ merge(Spinner.prototype, {
607
+
608
+ /**
609
+ * Adds the spinner to the given target element. If this instance is already
610
+ * spinning, it is automatically removed from its previous target b calling
611
+ * stop() internally.
612
+ */
613
+ spin: function(target) {
614
+ this.stop()
615
+
616
+ var self = this
617
+ , o = self.opts
618
+ , el = self.el = css(createEl(0, {className: o.className}), {position: o.position, width: 0, zIndex: o.zIndex})
619
+ , mid = o.radius+o.length+o.width
620
+ , ep // element position
621
+ , tp // target position
622
+
623
+ if (target) {
624
+ target.insertBefore(el, target.firstChild||null)
625
+ tp = pos(target)
626
+ ep = pos(el)
627
+ css(el, {
628
+ left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : parseInt(o.left, 10) + mid) + 'px',
629
+ top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : parseInt(o.top, 10) + mid) + 'px'
630
+ })
631
+ }
632
+
633
+ el.setAttribute('role', 'progressbar')
634
+ self.lines(el, self.opts)
635
+
636
+ if (!useCssAnimations) {
637
+ // No CSS animation support, use setTimeout() instead
638
+ var i = 0
639
+ , start = (o.lines - 1) * (1 - o.direction) / 2
640
+ , alpha
641
+ , fps = o.fps
642
+ , f = fps/o.speed
643
+ , ostep = (1-o.opacity) / (f*o.trail / 100)
644
+ , astep = f/o.lines
645
+
646
+ ;(function anim() {
647
+ i++;
648
+ for (var j = 0; j < o.lines; j++) {
649
+ alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity)
650
+
651
+ self.opacity(el, j * o.direction + start, alpha, o)
652
+ }
653
+ self.timeout = self.el && setTimeout(anim, ~~(1000/fps))
654
+ })()
655
+ }
656
+ return self
657
+ },
658
+
659
+ /**
660
+ * Stops and removes the Spinner.
661
+ */
662
+ stop: function() {
663
+ var el = this.el
664
+ if (el) {
665
+ clearTimeout(this.timeout)
666
+ if (el.parentNode) el.parentNode.removeChild(el)
667
+ this.el = undefined
668
+ }
669
+ return this
670
+ },
671
+
672
+ /**
673
+ * Internal method that draws the individual lines. Will be overwritten
674
+ * in VML fallback mode below.
675
+ */
676
+ lines: function(el, o) {
677
+ var i = 0
678
+ , start = (o.lines - 1) * (1 - o.direction) / 2
679
+ , seg
680
+
681
+ function fill(color, shadow) {
682
+ return css(createEl(), {
683
+ position: 'absolute',
684
+ width: (o.length+o.width) + 'px',
685
+ height: o.width + 'px',
686
+ background: color,
687
+ boxShadow: shadow,
688
+ transformOrigin: 'left',
689
+ transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
690
+ borderRadius: (o.corners * o.width>>1) + 'px'
691
+ })
692
+ }
693
+
694
+ for (; i < o.lines; i++) {
695
+ seg = css(createEl(), {
696
+ position: 'absolute',
697
+ top: 1+~(o.width/2) + 'px',
698
+ transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
699
+ opacity: o.opacity,
700
+ animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite'
701
+ })
702
+
703
+ if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}))
704
+ ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)')))
705
+ }
706
+ return el
707
+ },
708
+
709
+ /**
710
+ * Internal method that adjusts the opacity of a single line.
711
+ * Will be overwritten in VML fallback mode below.
712
+ */
713
+ opacity: function(el, i, val) {
714
+ if (i < el.childNodes.length) el.childNodes[i].style.opacity = val
715
+ }
716
+
717
+ })
718
+
719
+
720
+ function initVML() {
721
+
722
+ /* Utility function to create a VML tag */
723
+ function vml(tag, attr) {
724
+ return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr)
725
+ }
726
+
727
+ // No CSS transforms but VML support, add a CSS rule for VML elements:
728
+ sheet.addRule('.spin-vml', 'behavior:url(#default#VML)')
729
+
730
+ Spinner.prototype.lines = function(el, o) {
731
+ var r = o.length+o.width
732
+ , s = 2*r
733
+
734
+ function grp() {
735
+ return css(
736
+ vml('group', {
737
+ coordsize: s + ' ' + s,
738
+ coordorigin: -r + ' ' + -r
739
+ }),
740
+ { width: s, height: s }
741
+ )
742
+ }
743
+
744
+ var margin = -(o.width+o.length)*2 + 'px'
745
+ , g = css(grp(), {position: 'absolute', top: margin, left: margin})
746
+ , i
747
+
748
+ function seg(i, dx, filter) {
749
+ ins(g,
750
+ ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
751
+ ins(css(vml('roundrect', {arcsize: o.corners}), {
752
+ width: r,
753
+ height: o.width,
754
+ left: o.radius,
755
+ top: -o.width>>1,
756
+ filter: filter
757
+ }),
758
+ vml('fill', {color: getColor(o.color, i), opacity: o.opacity}),
759
+ vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
760
+ )
761
+ )
762
+ )
763
+ }
764
+
765
+ if (o.shadow)
766
+ for (i = 1; i <= o.lines; i++)
767
+ seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)')
768
+
769
+ for (i = 1; i <= o.lines; i++) seg(i)
770
+ return ins(el, g)
771
+ }
772
+
773
+ Spinner.prototype.opacity = function(el, i, val, o) {
774
+ var c = el.firstChild
775
+ o = o.shadow && o.lines || 0
776
+ if (c && i+o < c.childNodes.length) {
777
+ c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild
778
+ if (c) c.opacity = val
779
+ }
780
+ }
781
+ }
782
+
783
+ var probe = css(createEl('group'), {behavior: 'url(#default#VML)'})
784
+
785
+ if (!vendor(probe, 'transform') && probe.adj) initVML()
786
+ else useCssAnimations = vendor(probe, 'animation')
787
+
788
+ return Spinner
789
+
790
+ }));
791
+
792
+ /* Bez v1.0.10-g5ae0136
793
+ * http://github.com/rdallasgray/bez
794
+ *
795
+ * A plugin to convert CSS3 cubic-bezier co-ordinates to jQuery-compatible easing functions
796
+ *
797
+ * With thanks to Nikolay Nemshilov for clarification on the cubic-bezier maths
798
+ * See http://st-on-it.blogspot.com/2011/05/calculating-cubic-bezier-function.html
799
+ *
800
+ * Copyright 2011 Robert Dallas Gray. All rights reserved.
801
+ * Provided under the FreeBSD license: https://github.com/rdallasgray/bez/blob/master/LICENSE.txt
802
+ */
803
+ function bez (coOrdArray) {
804
+ var encodedFuncName = "bez_" + $.makeArray(arguments).join("_").replace(".", "p");
805
+ if (typeof $['easing'][encodedFuncName] !== "function") {
806
+ var polyBez = function (p1, p2) {
807
+ var A = [null, null],
808
+ B = [null, null],
809
+ C = [null, null],
810
+ bezCoOrd = function (t, ax) {
811
+ C[ax] = 3 * p1[ax];
812
+ B[ax] = 3 * (p2[ax] - p1[ax]) - C[ax];
813
+ A[ax] = 1 - C[ax] - B[ax];
814
+ return t * (C[ax] + t * (B[ax] + t * A[ax]));
815
+ },
816
+ xDeriv = function (t) {
817
+ return C[0] + t * (2 * B[0] + 3 * A[0] * t);
818
+ },
819
+ xForT = function (t) {
820
+ var x = t, i = 0, z;
821
+ while (++i < 14) {
822
+ z = bezCoOrd(x, 0) - t;
823
+ if (Math.abs(z) < 1e-3) break;
824
+ x -= z / xDeriv(x);
825
+ }
826
+ return x;
827
+ };
828
+ return function (t) {
829
+ return bezCoOrd(xForT(t), 1);
830
+ }
831
+ };
832
+ $['easing'][encodedFuncName] = function (x, t, b, c, d) {
833
+ return c * polyBez([coOrdArray[0], coOrdArray[1]], [coOrdArray[2], coOrdArray[3]])(t / d) + b;
834
+ }
835
+ }
836
+ return encodedFuncName;
837
+ }
838
+ var $WINDOW = $(window),
839
+ $DOCUMENT = $(document),
840
+ $HTML,
841
+ $BODY,
842
+
843
+ QUIRKS_FORCE = location.hash.replace('#', '') === 'quirks',
844
+ TRANSFORMS3D = Modernizr.csstransforms3d,
845
+ CSS3 = TRANSFORMS3D && !QUIRKS_FORCE,
846
+ COMPAT = TRANSFORMS3D || document.compatMode === 'CSS1Compat',
847
+ FULLSCREEN = fullScreenApi.ok,
848
+
849
+ MOBILE = navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i),
850
+ SLOW = !CSS3 || MOBILE,
851
+
852
+ MS_POINTER = navigator.msPointerEnabled,
853
+
854
+ WHEEL = "onwheel" in document.createElement("div") ? "wheel" : document.onmousewheel !== undefined ? "mousewheel" : "DOMMouseScroll",
855
+
856
+ TOUCH_TIMEOUT = 250,
857
+ TRANSITION_DURATION = 300,
858
+
859
+ SCROLL_LOCK_TIMEOUT = 1400,
860
+
861
+ AUTOPLAY_INTERVAL = 5000,
862
+ MARGIN = 2,
863
+ THUMB_SIZE = 64,
864
+
865
+ WIDTH = 500,
866
+ HEIGHT = 333,
867
+
868
+ STAGE_FRAME_KEY = '$stageFrame',
869
+ NAV_DOT_FRAME_KEY = '$navDotFrame',
870
+ NAV_THUMB_FRAME_KEY = '$navThumbFrame',
871
+
872
+ AUTO = 'auto',
873
+
874
+ BEZIER = bez([.1, 0, .25, 1]),
875
+
876
+ MAX_WIDTH = 99999,
877
+
878
+ FIFTYFIFTY = '50%',
879
+
880
+ OPTIONS = {
881
+ // dimensions
882
+ width: null, // 500 || '100%'
883
+ minwidth: null,
884
+ maxwidth: '100%', // '100%'
885
+ height: null,
886
+ minheight: null,
887
+ maxheight: null,
888
+
889
+ ratio: null, // '16/9' || 500/333 || 1.5
890
+
891
+ margin: MARGIN,
892
+ glimpse: 0,
893
+
894
+ fit: 'contain', // 'cover' || 'scaledown' || 'none'
895
+
896
+ position: FIFTYFIFTY,
897
+ thumbposition: FIFTYFIFTY,
898
+
899
+ // navigation, thumbs
900
+ nav: 'dots', // 'thumbs' || false
901
+ navposition: 'bottom', // 'top'
902
+ navwidth: null,
903
+ thumbwidth: THUMB_SIZE,
904
+ thumbheight: THUMB_SIZE,
905
+ thumbmargin: MARGIN,
906
+ thumbborderwidth: MARGIN,
907
+ thumbfit: 'cover', // 'contain' || 'scaledown' || 'none'
908
+
909
+ allowfullscreen: false, // true || 'native'
910
+
911
+ transition: 'slide', // 'crossfade' || 'dissolve'
912
+ clicktransition: null,
913
+ transitionduration: TRANSITION_DURATION,
914
+
915
+ captions: true,
916
+
917
+ hash: false,
918
+ startindex: 0,
919
+
920
+ loop: false,
921
+
922
+ autoplay: false,
923
+ stopautoplayontouch: true,
924
+
925
+ keyboard: false,
926
+
927
+ arrows: true,
928
+ click: true,
929
+ swipe: true,
930
+ trackpad: false,
931
+
932
+ enableifsingleframe: false,
933
+
934
+ controlsonstart: true,
935
+
936
+ shuffle: false,
937
+
938
+ direction: 'ltr', // 'rtl'
939
+
940
+ shadows: true,
941
+ spinner: null
942
+ },
943
+
944
+ KEYBOARD_OPTIONS = {
945
+ left: true,
946
+ right: true,
947
+ down: false,
948
+ up: false,
949
+ space: false,
950
+ home: false,
951
+ end: false
952
+ };
953
+ function noop () {}
954
+
955
+ function minMaxLimit (value, min, max) {
956
+ return Math.max(isNaN(min) ? -Infinity : min, Math.min(isNaN(max) ? Infinity : max, value));
957
+ }
958
+
959
+ function readTransform (css) {
960
+ return css.match(/ma/) && css.match(/-?\d+(?!d)/g)[css.match(/3d/) ? 12 : 4];
961
+ }
962
+
963
+ function readPosition ($el) {
964
+ if (CSS3) {
965
+ return +readTransform($el.css('transform'));
966
+ } else {
967
+ return +$el.css('left').replace('px', '');
968
+ }
969
+ }
970
+
971
+ function getTranslate (pos/*, _001*/) {
972
+ var obj = {};
973
+ if (CSS3) {
974
+ obj.transform = 'translate3d(' + (pos/* + (_001 ? 0.001 : 0)*/) + 'px,0,0)'; // 0.001 to remove Retina artifacts
975
+ } else {
976
+ obj.left = pos;
977
+ }
978
+ return obj;
979
+ }
980
+
981
+ function getDuration (time) {
982
+ return {'transition-duration': time + 'ms'};
983
+ }
984
+
985
+ function unlessNaN (value, alternative) {
986
+ return isNaN(value) ? alternative : value;
987
+ }
988
+
989
+ function numberFromMeasure (value, measure) {
990
+ return unlessNaN(+String(value).replace(measure || 'px', ''));
991
+ }
992
+
993
+ function numberFromPercent (value) {
994
+ return /%$/.test(value) ? numberFromMeasure(value, '%') : undefined;
995
+ }
996
+
997
+ function numberFromWhatever (value, whole) {
998
+ return unlessNaN(numberFromPercent(value) / 100 * whole, numberFromMeasure(value));
999
+ }
1000
+
1001
+ function measureIsValid (value) {
1002
+ return (!isNaN(numberFromMeasure(value)) || !isNaN(numberFromMeasure(value, '%'))) && value;
1003
+ }
1004
+
1005
+ function getPosByIndex (index, side, margin, baseIndex) {
1006
+ //console.log('getPosByIndex', index, side, margin, baseIndex);
1007
+ //console.log((index - (baseIndex || 0)) * (side + (margin || 0)));
1008
+
1009
+ return (index - (baseIndex || 0)) * (side + (margin || 0));
1010
+ }
1011
+
1012
+ function getIndexByPos (pos, side, margin, baseIndex) {
1013
+ return -Math.round(pos / (side + (margin || 0)) - (baseIndex || 0));
1014
+ }
1015
+
1016
+ function bindTransitionEnd ($el) {
1017
+ var elData = $el.data();
1018
+
1019
+ if (elData.tEnd) return;
1020
+
1021
+ var el = $el[0],
1022
+ transitionEndEvent = {
1023
+ WebkitTransition: 'webkitTransitionEnd',
1024
+ MozTransition: 'transitionend',
1025
+ OTransition: 'oTransitionEnd otransitionend',
1026
+ msTransition: 'MSTransitionEnd',
1027
+ transition: 'transitionend'
1028
+ };
1029
+ addEvent(el, transitionEndEvent[Modernizr.prefixed('transition')], function (e) {
1030
+ elData.tProp && e.propertyName.match(elData.tProp) && elData.onEndFn();
1031
+ });
1032
+ elData.tEnd = true;
1033
+ }
1034
+
1035
+ function afterTransition ($el, property, fn, time) {
1036
+ var ok,
1037
+ elData = $el.data();
1038
+
1039
+ if (elData) {
1040
+ elData.onEndFn = function () {
1041
+ if (ok) return;
1042
+ ok = true;
1043
+ clearTimeout(elData.tT);
1044
+ fn();
1045
+ };
1046
+ elData.tProp = property;
1047
+
1048
+ // Passive call, just in case of fail of native transition-end event
1049
+ clearTimeout(elData.tT);
1050
+ elData.tT = setTimeout(function () {
1051
+ elData.onEndFn();
1052
+ }, time * 1.5);
1053
+
1054
+ bindTransitionEnd($el);
1055
+ }
1056
+ }
1057
+
1058
+
1059
+ function stop ($el, left/*, _001*/) {
1060
+ if ($el.length) {
1061
+ var elData = $el.data();
1062
+ if (CSS3) {
1063
+ $el.css(getDuration(0));
1064
+ elData.onEndFn = noop;
1065
+ clearTimeout(elData.tT);
1066
+ } else {
1067
+ $el.stop();
1068
+ }
1069
+ var lockedLeft = getNumber(left, function () {
1070
+ return readPosition($el);
1071
+ });
1072
+
1073
+ $el.css(getTranslate(lockedLeft/*, _001*/));//.width(); // `.width()` for reflow
1074
+ return lockedLeft;
1075
+ }
1076
+ }
1077
+
1078
+ function getNumber () {
1079
+ var number;
1080
+ for (var _i = 0, _l = arguments.length; _i < _l; _i++) {
1081
+ number = _i ? arguments[_i]() : arguments[_i];
1082
+ if (typeof number === 'number') {
1083
+ break;
1084
+ }
1085
+ }
1086
+
1087
+ return number;
1088
+ }
1089
+
1090
+ function edgeResistance (pos, edge) {
1091
+ return Math.round(pos + ((edge - pos) / 1.5));
1092
+ }
1093
+
1094
+ function getProtocol () {
1095
+ getProtocol.p = getProtocol.p || (location.protocol === 'https:' ? 'https://' : 'http://');
1096
+ return getProtocol.p;
1097
+ }
1098
+
1099
+ function parseHref (href) {
1100
+ var a = document.createElement('a');
1101
+ a.href = href;
1102
+ return a;
1103
+ }
1104
+
1105
+ function findVideoId (href, forceVideo) {
1106
+ if (typeof href !== 'string') return href;
1107
+ href = parseHref(href);
1108
+
1109
+ var id,
1110
+ type;
1111
+
1112
+ if (href.host.match(/youtube\.com/) && href.search) {
1113
+ //.log();
1114
+ id = href.search.split('v=')[1];
1115
+ if (id) {
1116
+ var ampersandPosition = id.indexOf('&');
1117
+ if (ampersandPosition !== -1) {
1118
+ id = id.substring(0, ampersandPosition);
1119
+ }
1120
+ type = 'youtube';
1121
+ }
1122
+ } else if (href.host.match(/youtube\.com|youtu\.be/)) {
1123
+ id = href.pathname.replace(/^\/(embed\/|v\/)?/, '').replace(/\/.*/, '');
1124
+ type = 'youtube';
1125
+ } else if (href.host.match(/vimeo\.com/)) {
1126
+ type = 'vimeo';
1127
+ id = href.pathname.replace(/^\/(video\/)?/, '').replace(/\/.*/, '');
1128
+ }
1129
+
1130
+ if ((!id || !type) && forceVideo) {
1131
+ id = href.href;
1132
+ type = 'custom';
1133
+ }
1134
+
1135
+ return id ? {id: id, type: type, s: href.search.replace(/^\?/, ''), p: getProtocol()} : false;
1136
+ }
1137
+
1138
+ function getVideoThumbs (dataFrame, data, fotorama) {
1139
+ var img, thumb, video = dataFrame.video;
1140
+ if (video.type === 'youtube') {
1141
+ thumb = getProtocol() + 'img.youtube.com/vi/' + video.id + '/default.jpg';
1142
+ img = thumb.replace(/\/default.jpg$/, '/hqdefault.jpg');
1143
+ dataFrame.thumbsReady = true;
1144
+ } else if (video.type === 'vimeo') {
1145
+ $.ajax({
1146
+ url: getProtocol() + 'vimeo.com/api/v2/video/' + video.id + '.json',
1147
+ dataType: 'jsonp',
1148
+ success: function (json) {
1149
+ dataFrame.thumbsReady = true;
1150
+ updateData(data, {img: json[0].thumbnail_large, thumb: json[0].thumbnail_small}, dataFrame.i, fotorama);
1151
+ }
1152
+ });
1153
+ } else {
1154
+ dataFrame.thumbsReady = true;
1155
+ }
1156
+
1157
+ return {
1158
+ img: img,
1159
+ thumb: thumb
1160
+ }
1161
+ }
1162
+
1163
+ function updateData (data, _dataFrame, i, fotorama) {
1164
+ for (var _i = 0, _l = data.length; _i < _l; _i++) {
1165
+ var dataFrame = data[_i];
1166
+
1167
+ if (dataFrame.i === i && dataFrame.thumbsReady) {
1168
+ var clear = {videoReady: true};
1169
+ clear[STAGE_FRAME_KEY] = clear[NAV_THUMB_FRAME_KEY] = clear[NAV_DOT_FRAME_KEY] = false;
1170
+
1171
+ fotorama.splice(_i, 1, $.extend(
1172
+ {},
1173
+ dataFrame,
1174
+ clear,
1175
+ _dataFrame
1176
+ ));
1177
+
1178
+ break;
1179
+ }
1180
+ }
1181
+ }
1182
+
1183
+ function getDataFromHtml ($el) {
1184
+ var data = [];
1185
+
1186
+ function getDataFromImg ($img, imgData, checkVideo) {
1187
+ var $child = $img.children('img').eq(0),
1188
+ _imgHref = $img.attr('href'),
1189
+ _imgSrc = $img.attr('src'),
1190
+ _thumbSrc = $child.attr('src'),
1191
+ _video = imgData.video,
1192
+ video = checkVideo ? findVideoId(_imgHref, _video === true) : false;
1193
+
1194
+ if (video) {
1195
+ _imgHref = false;
1196
+ } else {
1197
+ video = _video;
1198
+ }
1199
+
1200
+ getDimensions($img, $child, $.extend(imgData, {
1201
+ video: video,
1202
+ img: imgData.img || _imgHref || _imgSrc || _thumbSrc,
1203
+ thumb: imgData.thumb || _thumbSrc || _imgSrc || _imgHref
1204
+ }));
1205
+ }
1206
+
1207
+ function getDimensions ($img, $child, imgData) {
1208
+ var separateThumbFLAG = imgData.thumb && imgData.img !== imgData.thumb,
1209
+ width = numberFromMeasure(imgData.width || $img.attr('width')),
1210
+ height = numberFromMeasure(imgData.height || $img.attr('height'));
1211
+
1212
+ $.extend(imgData, {
1213
+ width: width,
1214
+ height: height,
1215
+ thumbratio: getRatio(imgData.thumbratio || (numberFromMeasure(imgData.thumbwidth || ($child && $child.attr('width')) || separateThumbFLAG || width) / numberFromMeasure(imgData.thumbheight || ($child && $child.attr('height')) || separateThumbFLAG || height)))
1216
+ });
1217
+ }
1218
+
1219
+ $el.children().each(function () {
1220
+ var $this = $(this),
1221
+ dataFrame = optionsToLowerCase($.extend($this.data(), {id: $this.attr('id')}));
1222
+ if ($this.is('a, img')) {
1223
+ getDataFromImg($this, dataFrame, true);
1224
+ } else if (!$this.is(':empty')) {
1225
+ getDimensions($this, null, $.extend(dataFrame, {
1226
+ html: this,
1227
+ _html: $this.html() // Because of IE
1228
+ }));
1229
+ } else return;
1230
+
1231
+ data.push(dataFrame);
1232
+ });
1233
+
1234
+ return data;
1235
+ }
1236
+
1237
+ function isHidden (el) {
1238
+ return el.offsetWidth === 0 && el.offsetHeight === 0;
1239
+ }
1240
+
1241
+ function isDetached (el) {
1242
+ return !$.contains(document.documentElement, el);
1243
+ }
1244
+
1245
+ function waitFor (test, fn, timeout, i) {
1246
+ if (!waitFor.i) {
1247
+ waitFor.i = 1;
1248
+ waitFor.ii = [true];
1249
+ }
1250
+
1251
+ i = i || waitFor.i;
1252
+
1253
+ if (typeof waitFor.ii[i] === 'undefined') {
1254
+ waitFor.ii[i] = true;
1255
+ }
1256
+
1257
+ if (test()) {
1258
+ fn();
1259
+ } else {
1260
+ waitFor.ii[i] && setTimeout(function () {
1261
+ waitFor.ii[i] && waitFor(test, fn, timeout, i);
1262
+ }, timeout || 100);
1263
+ }
1264
+
1265
+ return waitFor.i++;
1266
+ }
1267
+
1268
+ waitFor.stop = function (i) {
1269
+ waitFor.ii[i] = false;
1270
+ };
1271
+
1272
+ function setHash (hash) {
1273
+ ////console.time('setHash ' + hash);
1274
+ location.replace(location.protocol
1275
+ + '//'
1276
+ + location.host
1277
+ + location.pathname.replace(/^\/?/, '/')
1278
+ + location.search
1279
+ + '#' + hash);
1280
+ ////console.timeEnd('setHash ' + hash);
1281
+ }
1282
+
1283
+ function fit ($el, measuresToFit, method, position) {
1284
+ var elData = $el.data(),
1285
+ measures = elData.measures;
1286
+
1287
+ if (measures && (!elData.l ||
1288
+ elData.l.W !== measures.width ||
1289
+ elData.l.H !== measures.height ||
1290
+ elData.l.r !== measures.ratio ||
1291
+ elData.l.w !== measuresToFit.w ||
1292
+ elData.l.h !== measuresToFit.h ||
1293
+ elData.l.m !== method ||
1294
+ elData.l.p !== position)) {
1295
+
1296
+ console.log('fit');
1297
+
1298
+ var width = measures.width,
1299
+ height = measures.height,
1300
+ ratio = measuresToFit.w / measuresToFit.h,
1301
+ biggerRatioFLAG = measures.ratio >= ratio,
1302
+ fitFLAG = method === 'scaledown',
1303
+ containFLAG = method === 'contain',
1304
+ coverFLAG = method === 'cover',
1305
+ pos = parsePosition(position);
1306
+
1307
+ if (biggerRatioFLAG && (fitFLAG || containFLAG) || !biggerRatioFLAG && coverFLAG) {
1308
+ width = minMaxLimit(measuresToFit.w, 0, fitFLAG ? width : Infinity);
1309
+ height = width / measures.ratio;
1310
+ } else if (biggerRatioFLAG && coverFLAG || !biggerRatioFLAG && (fitFLAG || containFLAG)) {
1311
+ height = minMaxLimit(measuresToFit.h, 0, fitFLAG ? height : Infinity);
1312
+ width = height * measures.ratio;
1313
+ }
1314
+
1315
+ $el.css({
1316
+ width: width,
1317
+ height: height,
1318
+ left: numberFromWhatever(pos.x, measuresToFit.w - width),
1319
+ top: numberFromWhatever(pos.y, measuresToFit.h- height)
1320
+ });
1321
+
1322
+ elData.l = {
1323
+ W: measures.width,
1324
+ H: measures.height,
1325
+ r: measures.ratio,
1326
+ w: measuresToFit.w,
1327
+ h: measuresToFit.h,
1328
+ m: method,
1329
+ p: position
1330
+ };
1331
+ }
1332
+
1333
+ return true;
1334
+ }
1335
+
1336
+ function setStyle ($el, style) {
1337
+ var el = $el[0];
1338
+ if (el.styleSheet) {
1339
+ el.styleSheet.cssText = style;
1340
+ } else {
1341
+ $el.html(style);
1342
+ }
1343
+ }
1344
+
1345
+ function findShadowEdge (pos, min, max) {
1346
+ return min === max ? false : pos <= min ? 'left' : pos >= max ? 'right' : 'left right';
1347
+ }
1348
+
1349
+ function getIndexFromHash (hash, data, ok, startindex) {
1350
+ if (!ok) return false;
1351
+ if (!isNaN(hash)) return hash - (startindex ? 0 : 1);
1352
+
1353
+ var index;
1354
+
1355
+ for (var _i = 0, _l = data.length; _i < _l; _i++) {
1356
+ var dataFrame = data[_i];
1357
+
1358
+ if (dataFrame.id === hash) {
1359
+ index = _i;
1360
+ break;
1361
+ }
1362
+ }
1363
+
1364
+ return index;
1365
+ }
1366
+
1367
+ function smartClick ($el, fn, _options) {
1368
+ _options = _options || {};
1369
+
1370
+ $el.each(function () {
1371
+ var $this = $(this),
1372
+ thisData = $this.data(),
1373
+ startEvent;
1374
+
1375
+ if (thisData.clickOn) return;
1376
+
1377
+ thisData.clickOn = true;
1378
+
1379
+ $.extend(touch($this, {
1380
+ onStart: function (e) {
1381
+ startEvent = e;
1382
+ (_options.onStart || noop).call(this, e);
1383
+ },
1384
+ onMove: _options.onMove || noop,
1385
+ onTouchEnd: _options.onTouchEnd || noop,
1386
+ onEnd: function (result) {
1387
+ //console.log('smartClick → result.moved', result.moved);
1388
+ if (result.moved) return;
1389
+ fn.call(this, startEvent);
1390
+ }
1391
+ }), {noMove: true});
1392
+ });
1393
+ }
1394
+
1395
+ function div (classes, child) {
1396
+ return '<div class="' + classes + '">' + (child || '') + '</div>';
1397
+ }
1398
+
1399
+ // Fisher–Yates Shuffle
1400
+ // http://bost.ocks.org/mike/shuffle/
1401
+ function shuffle (array) {
1402
+ // While there remain elements to shuffle
1403
+ var l = array.length;
1404
+ while (l) {
1405
+ // Pick a remaining element
1406
+ var i = Math.floor(Math.random() * l--);
1407
+
1408
+ // And swap it with the current element
1409
+ var t = array[l];
1410
+ array[l] = array[i];
1411
+ array[i] = t;
1412
+ }
1413
+
1414
+ return array;
1415
+ }
1416
+
1417
+ function clone (array) {
1418
+ return Object.prototype.toString.call(array) == '[object Array]'
1419
+ && $.map(array, function (frame) {
1420
+ return $.extend({}, frame);
1421
+ });
1422
+ }
1423
+
1424
+ function lockScroll ($el, left, top) {
1425
+ $el
1426
+ .scrollLeft(left || 0)
1427
+ .scrollTop(top || 0);
1428
+ }
1429
+
1430
+ function optionsToLowerCase (options) {
1431
+ if (options) {
1432
+ var opts = {};
1433
+ $.each(options, function (key, value) {
1434
+ opts[key.toLowerCase()] = value;
1435
+ });
1436
+
1437
+ return opts;
1438
+ }
1439
+ }
1440
+
1441
+ function getRatio (_ratio) {
1442
+ if (!_ratio) return;
1443
+ var ratio = +_ratio;
1444
+ if (!isNaN(ratio)) {
1445
+ return ratio;
1446
+ } else {
1447
+ ratio = _ratio.split('/');
1448
+ return +ratio[0] / +ratio[1] || undefined;
1449
+ }
1450
+ }
1451
+
1452
+ function addEvent (el, e, fn, bool) {
1453
+ if (!e) return;
1454
+ el.addEventListener ? el.addEventListener(e, fn, !!bool) : el.attachEvent('on'+e, fn);
1455
+ }
1456
+
1457
+ function elIsDisabled (el) {
1458
+ return !!el.getAttribute('disabled');
1459
+ }
1460
+
1461
+ function disableAttr (FLAG) {
1462
+ return {tabindex: FLAG * -1 + '', disabled: FLAG};
1463
+ }
1464
+
1465
+ function addEnterUp (el, fn) {
1466
+ addEvent(el, 'keyup', function (e) {
1467
+ elIsDisabled(el) || e.keyCode == 13 && fn.call(el, e);
1468
+ });
1469
+ }
1470
+
1471
+ function addFocus (el, fn) {
1472
+ addEvent(el, 'focus', el.onfocusin = function (e) {
1473
+ fn.call(el, e);
1474
+ }, true);
1475
+ }
1476
+
1477
+ function stopEvent (e, stopPropagation) {
1478
+ e.preventDefault ? e.preventDefault() : (e.returnValue = false);
1479
+ stopPropagation && e.stopPropagation && e.stopPropagation();
1480
+ }
1481
+
1482
+ function getDirectionSign (forward) {
1483
+ return forward ? '>' : '<';
1484
+ }
1485
+
1486
+ function parsePosition (rule) {
1487
+ rule = (rule + '').split(/\s+/);
1488
+ return {
1489
+ x: measureIsValid(rule[0]) || FIFTYFIFTY,
1490
+ y: measureIsValid(rule[1]) || FIFTYFIFTY
1491
+ }
1492
+ }
1493
+ function slide ($el, options) {
1494
+ var elData = $el.data(),
1495
+ elPos = Math.round(options.pos),
1496
+ onEndFn = function () {
1497
+ elData.sliding = false;
1498
+ (options.onEnd || noop)();
1499
+ };
1500
+
1501
+ if (typeof options.overPos !== 'undefined' && options.overPos !== options.pos) {
1502
+ elPos = options.overPos;
1503
+ onEndFn = function () {
1504
+ slide($el, $.extend({}, options, {overPos: options.pos, time: Math.max(TRANSITION_DURATION, options.time / 2)}))
1505
+ };
1506
+ }
1507
+
1508
+ //////console.time('var translate = $.extend');
1509
+ var translate = $.extend(getTranslate(elPos/*, options._001*/), options.width && {width: options.width});
1510
+ //////console.timeEnd('var translate = $.extend');
1511
+
1512
+ elData.sliding = true;
1513
+
1514
+ if (CSS3) {
1515
+ $el.css($.extend(getDuration(options.time), translate));
1516
+ if (options.time > 10) {
1517
+ //////console.time('afterTransition');
1518
+ afterTransition($el, 'transform', onEndFn, options.time);
1519
+ //////console.timeEnd('afterTransition');
1520
+ } else {
1521
+ onEndFn();
1522
+ }
1523
+ } else {
1524
+ $el.stop().animate(translate, options.time, BEZIER, onEndFn);
1525
+ }
1526
+ }
1527
+
1528
+ function fade ($el1, $el2, $frames, options, fadeStack, chain) {
1529
+ var chainedFLAG = typeof chain !== 'undefined';
1530
+ if (!chainedFLAG) {
1531
+ fadeStack.push(arguments);
1532
+ Array.prototype.push.call(arguments, fadeStack.length);
1533
+ if (fadeStack.length > 1) return;
1534
+ }
1535
+
1536
+ $el1 = $el1 || $($el1);
1537
+ $el2 = $el2 || $($el2);
1538
+
1539
+ var _$el1 = $el1[0],
1540
+ _$el2 = $el2[0],
1541
+ crossfadeFLAG = options.method === 'crossfade',
1542
+ onEndFn = function () {
1543
+ if (!onEndFn.done) {
1544
+ onEndFn.done = true;
1545
+ var args = (chainedFLAG || fadeStack.shift()) && fadeStack.shift();
1546
+ args && fade.apply(this, args);
1547
+ (options.onEnd || noop)(!!args);
1548
+ }
1549
+ },
1550
+ time = options.time / (chain || 1);
1551
+
1552
+ $frames.removeClass(fadeRearClass + ' ' + fadeFrontClass);
1553
+
1554
+ $el1
1555
+ .stop()
1556
+ .addClass(fadeRearClass);
1557
+ $el2
1558
+ .stop()
1559
+ .addClass(fadeFrontClass);
1560
+
1561
+ crossfadeFLAG && _$el2 && $el1.fadeTo(0, 0);
1562
+
1563
+ $el1.fadeTo(crossfadeFLAG ? time : 0, 1, crossfadeFLAG && onEndFn);
1564
+ $el2.fadeTo(time, 0, onEndFn);
1565
+
1566
+ (_$el1 && crossfadeFLAG) || _$el2 || onEndFn();
1567
+ }
1568
+ var lastEvent,
1569
+ moveEventType,
1570
+ preventEvent,
1571
+ preventEventTimeout;
1572
+
1573
+ function extendEvent (e) {
1574
+ var touch = (e.touches || [])[0] || e;
1575
+ e._x = touch.pageX;
1576
+ e._y = touch.clientY;
1577
+ e._now = $.now();
1578
+ }
1579
+
1580
+ function touch ($el, options) {
1581
+ var el = $el[0],
1582
+ tail = {},
1583
+ touchEnabledFLAG,
1584
+ startEvent,
1585
+ $target,
1586
+ controlTouch,
1587
+ touchFLAG,
1588
+ targetIsSelectFLAG,
1589
+ targetIsLinkFlag,
1590
+ tolerance,
1591
+ moved;
1592
+
1593
+ function onStart (e) {
1594
+ $target = $(e.target);
1595
+ tail.checked = targetIsSelectFLAG = targetIsLinkFlag = moved = false;
1596
+
1597
+ if (touchEnabledFLAG
1598
+ || tail.flow
1599
+ || (e.touches && e.touches.length > 1)
1600
+ || e.which > 1
1601
+ || (lastEvent && lastEvent.type !== e.type && preventEvent)
1602
+ || (targetIsSelectFLAG = options.select && $target.is(options.select, el))) return targetIsSelectFLAG;
1603
+
1604
+ touchFLAG = e.type === 'touchstart';
1605
+ targetIsLinkFlag = $target.is('a, a *', el);
1606
+ controlTouch = tail.control;
1607
+
1608
+ tolerance = (tail.noMove || tail.noSwipe || controlTouch) ? 16 : !tail.snap ? 4 : 0;
1609
+
1610
+ extendEvent(e);
1611
+
1612
+ startEvent = lastEvent = e;
1613
+ moveEventType = e.type.replace(/down|start/, 'move').replace(/Down/, 'Move');
1614
+
1615
+ (options.onStart || noop).call(el, e, {control: controlTouch, $target: $target});
1616
+
1617
+ touchEnabledFLAG = tail.flow = true;
1618
+
1619
+ if (!touchFLAG || tail.go) stopEvent(e);
1620
+ }
1621
+
1622
+ function onMove (e) {
1623
+ if ((e.touches && e.touches.length > 1)
1624
+ || (MS_POINTER && !e.isPrimary)
1625
+ || moveEventType !== e.type
1626
+ || !touchEnabledFLAG) {
1627
+ touchEnabledFLAG && onEnd();
1628
+ (options.onTouchEnd || noop)();
1629
+ return;
1630
+ }
1631
+
1632
+ extendEvent(e);
1633
+
1634
+ var xDiff = Math.abs(e._x - startEvent._x), // opt _x → _pageX
1635
+ yDiff = Math.abs(e._y - startEvent._y),
1636
+ xyDiff = xDiff - yDiff,
1637
+ xWin = (tail.go || tail.x || xyDiff >= 0) && !tail.noSwipe,
1638
+ yWin = xyDiff < 0;
1639
+
1640
+ if (touchFLAG && !tail.checked) {
1641
+ if (touchEnabledFLAG = xWin) {
1642
+ stopEvent(e);
1643
+ }
1644
+ } else {
1645
+ //console.log('onMove e.preventDefault');
1646
+ stopEvent(e);
1647
+ (options.onMove || noop).call(el, e, {touch: touchFLAG});
1648
+ }
1649
+
1650
+ if (!moved && Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2)) > tolerance) {
1651
+ moved = true;
1652
+ }
1653
+
1654
+ tail.checked = tail.checked || xWin || yWin;
1655
+ }
1656
+
1657
+ function onEnd (e) {
1658
+ ////console.time('touch.js onEnd');
1659
+
1660
+ (options.onTouchEnd || noop)();
1661
+
1662
+ var _touchEnabledFLAG = touchEnabledFLAG;
1663
+ tail.control = touchEnabledFLAG = false;
1664
+
1665
+ if (_touchEnabledFLAG) {
1666
+ tail.flow = false;
1667
+ }
1668
+
1669
+ if (!_touchEnabledFLAG || (targetIsLinkFlag && !tail.checked)) return;
1670
+
1671
+ e && stopEvent(e);
1672
+
1673
+ preventEvent = true;
1674
+ clearTimeout(preventEventTimeout);
1675
+ preventEventTimeout = setTimeout(function () {
1676
+ preventEvent = false;
1677
+ }, 1000);
1678
+
1679
+ (options.onEnd || noop).call(el, {moved: moved, $target: $target, control: controlTouch, touch: touchFLAG, startEvent: startEvent, aborted: !e || e.type === 'MSPointerCancel'});
1680
+ ////console.timeEnd('touch.js onEnd');
1681
+ }
1682
+
1683
+ function onOtherStart () {
1684
+ if (tail.flow) return;
1685
+ setTimeout(function () {
1686
+ tail.flow = true;
1687
+ }, 10);
1688
+ }
1689
+
1690
+ function onOtherEnd () {
1691
+ if (!tail.flow) return;
1692
+ setTimeout(function () {
1693
+ tail.flow = false;
1694
+ }, TOUCH_TIMEOUT);
1695
+ }
1696
+
1697
+ if (MS_POINTER) {
1698
+ addEvent(el, 'MSPointerDown', onStart);
1699
+ addEvent(document, 'MSPointerMove', onMove);
1700
+ addEvent(document,'MSPointerCancel', onEnd);
1701
+ addEvent(document, 'MSPointerUp', onEnd);
1702
+ } else {
1703
+ addEvent(el, 'touchstart', onStart);
1704
+ addEvent(el, 'touchmove', onMove);
1705
+ addEvent(el, 'touchend', onEnd);
1706
+
1707
+ addEvent(document, 'touchstart', onOtherStart);
1708
+ addEvent(document, 'touchend', onOtherEnd);
1709
+ addEvent(document, 'touchcancel', onOtherEnd);
1710
+
1711
+ $WINDOW.on('scroll', onOtherEnd);
1712
+
1713
+ $el.on('mousedown', onStart);
1714
+ $DOCUMENT
1715
+ .on('mousemove', onMove)
1716
+ .on('mouseup', onEnd);
1717
+ }
1718
+
1719
+ $el.on('click', 'a', function (e) {
1720
+ tail.checked && stopEvent(e);
1721
+ });
1722
+
1723
+ return tail;
1724
+ }
1725
+
1726
+ function moveOnTouch ($el, options) {
1727
+ var el = $el[0],
1728
+ elData = $el.data(),
1729
+ tail = {},
1730
+ startCoo,
1731
+ coo,
1732
+ startElPos,
1733
+ moveElPos,
1734
+ edge,
1735
+ moveTrack,
1736
+ startTime,
1737
+ endTime,
1738
+ min,
1739
+ max,
1740
+ snap,
1741
+ slowFLAG,
1742
+ controlFLAG,
1743
+ moved,
1744
+ tracked;
1745
+
1746
+ function startTracking (e, noStop) {
1747
+ tracked = true;
1748
+ startCoo = coo = e._x;
1749
+ startTime = e._now;
1750
+
1751
+ moveTrack = [
1752
+ [startTime, startCoo]
1753
+ ];
1754
+
1755
+ startElPos = moveElPos = tail.noMove || noStop ? 0 : stop($el, (options.getPos || noop)()/*, options._001*/);
1756
+
1757
+ (options.onStart || noop).call(el, e);
1758
+ }
1759
+
1760
+ function onStart (e, result) {
1761
+ min = tail.min;
1762
+ max = tail.max;
1763
+ snap = tail.snap;
1764
+
1765
+ slowFLAG = e.altKey;
1766
+ tracked = moved = false;
1767
+
1768
+ controlFLAG = result.control;
1769
+
1770
+ if (!controlFLAG && !elData.sliding) {
1771
+ startTracking(e);
1772
+ }
1773
+ }
1774
+
1775
+ function onMove (e, result) {
1776
+ if (!tail.noSwipe) {
1777
+ if (!tracked) {
1778
+ startTracking(e);
1779
+ }
1780
+
1781
+ coo = e._x;
1782
+
1783
+ moveTrack.push([e._now, coo]);
1784
+
1785
+ moveElPos = startElPos - (startCoo - coo);
1786
+
1787
+ edge = findShadowEdge(moveElPos, min, max);
1788
+
1789
+ if (moveElPos <= min) {
1790
+ moveElPos = edgeResistance(moveElPos, min);
1791
+ } else if (moveElPos >= max) {
1792
+ moveElPos = edgeResistance(moveElPos, max);
1793
+ }
1794
+
1795
+ if (!tail.noMove) {
1796
+ $el.css(getTranslate(moveElPos/*, options._001*/));
1797
+ if (!moved) {
1798
+ moved = true;
1799
+ // only for mouse
1800
+ result.touch || MS_POINTER || $el.addClass(grabbingClass);
1801
+ }
1802
+
1803
+ (options.onMove || noop).call(el, e, {pos: moveElPos, edge: edge});
1804
+ }
1805
+ }
1806
+ }
1807
+
1808
+ function onEnd (result) {
1809
+ ////console.time('moveontouch.js onEnd');
1810
+ if (tail.noSwipe && result.moved) return;
1811
+
1812
+ if (!tracked) {
1813
+ startTracking(result.startEvent, true);
1814
+ }
1815
+
1816
+ //console.log('onEnd');
1817
+
1818
+ result.touch || MS_POINTER || $el.removeClass(grabbingClass);
1819
+
1820
+ endTime = $.now();
1821
+
1822
+ var _backTimeIdeal = endTime - TOUCH_TIMEOUT,
1823
+ _backTime,
1824
+ _timeDiff,
1825
+ _timeDiffLast,
1826
+ backTime = null,
1827
+ backCoo,
1828
+ virtualPos,
1829
+ limitPos,
1830
+ newPos,
1831
+ overPos,
1832
+ time = TRANSITION_DURATION,
1833
+ speed,
1834
+ friction = options.friction;
1835
+
1836
+ for (var _i = moveTrack.length - 1; _i >= 0; _i--) {
1837
+ _backTime = moveTrack[_i][0];
1838
+ _timeDiff = Math.abs(_backTime - _backTimeIdeal);
1839
+ if (backTime === null || _timeDiff < _timeDiffLast) {
1840
+ backTime = _backTime;
1841
+ backCoo = moveTrack[_i][1];
1842
+ } else if (backTime === _backTimeIdeal || _timeDiff > _timeDiffLast) {
1843
+ break;
1844
+ }
1845
+ _timeDiffLast = _timeDiff;
1846
+ }
1847
+
1848
+ newPos = minMaxLimit(moveElPos, min, max);
1849
+
1850
+ var cooDiff = backCoo - coo,
1851
+ forwardFLAG = cooDiff >= 0,
1852
+ timeDiff = endTime - backTime,
1853
+ longTouchFLAG = timeDiff > TOUCH_TIMEOUT,
1854
+ swipeFLAG = !longTouchFLAG && moveElPos !== startElPos && newPos === moveElPos;
1855
+
1856
+ if (snap) {
1857
+ newPos = minMaxLimit(Math[swipeFLAG ? (forwardFLAG ? 'floor' : 'ceil') : 'round'](moveElPos / snap) * snap, min, max);
1858
+ min = max = newPos;
1859
+ }
1860
+
1861
+ if (swipeFLAG && (snap || newPos === moveElPos)) {
1862
+ speed = -(cooDiff / timeDiff);
1863
+ time *= minMaxLimit(Math.abs(speed), options.timeLow, options.timeHigh);
1864
+ virtualPos = Math.round(moveElPos + speed * time / friction);
1865
+
1866
+ if (!snap) {
1867
+ newPos = virtualPos;
1868
+ }
1869
+
1870
+ if (!forwardFLAG && virtualPos > max || forwardFLAG && virtualPos < min) {
1871
+ limitPos = forwardFLAG ? min : max;
1872
+ overPos = virtualPos - limitPos;
1873
+ if (!snap) {
1874
+ newPos = limitPos;
1875
+ }
1876
+ overPos = minMaxLimit(newPos + overPos * .03, limitPos - 50, limitPos + 50);
1877
+ time = Math.abs((moveElPos - overPos) / (speed / friction));
1878
+ }
1879
+ }
1880
+
1881
+ time *= slowFLAG ? 10 : 1;
1882
+
1883
+ (options.onEnd || noop).call(el, $.extend(result, {moved: result.moved || longTouchFLAG && snap, pos: moveElPos, newPos: newPos, overPos: overPos, time: time}));
1884
+ }
1885
+
1886
+ tail = $.extend(touch(options.$wrap, $.extend({}, options, {
1887
+ onStart: onStart,
1888
+ onMove: onMove,
1889
+ onEnd: onEnd
1890
+ })), tail);
1891
+
1892
+ return tail;
1893
+ }
1894
+ function wheel ($el, options) {
1895
+ var el = $el[0],
1896
+ lockFLAG,
1897
+ lastDirection,
1898
+ lastNow,
1899
+ tail = {
1900
+ prevent: {}
1901
+ };
1902
+
1903
+ addEvent(el, WHEEL, function (e) {
1904
+ var yDelta = e.wheelDeltaY || -1 * e.deltaY || 0,
1905
+ xDelta = e.wheelDeltaX || -1 * e.deltaX || 0,
1906
+ xWin = Math.abs(xDelta) && !Math.abs(yDelta),
1907
+ direction = getDirectionSign(xDelta < 0),
1908
+ sameDirection = lastDirection === direction,
1909
+ now = $.now(),
1910
+ tooFast = now - lastNow < TOUCH_TIMEOUT;
1911
+
1912
+ lastDirection = direction;
1913
+ lastNow = now;
1914
+
1915
+ if (!xWin || !tail.ok || tail.prevent[direction] && !lockFLAG) {
1916
+ return;
1917
+ } else {
1918
+ stopEvent(e, true);
1919
+ if (lockFLAG && sameDirection && tooFast) {
1920
+ return;
1921
+ }
1922
+ }
1923
+
1924
+ if (options.shift) {
1925
+ lockFLAG = true;
1926
+ clearTimeout(tail.t);
1927
+ tail.t = setTimeout(function () {
1928
+ lockFLAG = false;
1929
+ }, SCROLL_LOCK_TIMEOUT);
1930
+ }
1931
+
1932
+ (options.onEnd || noop)(e, options.shift ? direction : xDelta);
1933
+
1934
+ });
1935
+
1936
+ return tail;
1937
+ }
1938
+ jQuery.Fotorama = function ($fotorama, opts) {
1939
+ $HTML = $('html');
1940
+ $BODY = $('body');
1941
+
1942
+ var that = this,
1943
+ stamp = $.now(),
1944
+ stampClass = _fotoramaClass + stamp,
1945
+ fotorama = $fotorama[0],
1946
+ data,
1947
+ dataFrameCount = 1,
1948
+ fotoramaData = $fotorama.data(),
1949
+ size,
1950
+
1951
+ $style = $('<style></style>'),
1952
+
1953
+ $anchor = $(div(hiddenClass)),
1954
+ $wrap = $(div(wrapClass)),
1955
+ $stage = $(div(stageClass)).appendTo($wrap),
1956
+ stage = $stage[0],
1957
+
1958
+ $stageShaft = $(div(stageShaftClass)).appendTo($stage),
1959
+ $stageFrame = $(),
1960
+ $arrPrev = $(div(arrClass + ' ' + arrPrevClass + buttonAttributes)),
1961
+ $arrNext = $(div(arrClass + ' ' + arrNextClass + buttonAttributes)),
1962
+ $arrs = $arrPrev.add($arrNext).appendTo($stage),
1963
+ $navWrap = $(div(navWrapClass)),
1964
+ $nav = $(div(navClass)).appendTo($navWrap),
1965
+ $navShaft = $(div(navShaftClass)).appendTo($nav),
1966
+ $navFrame,
1967
+ $navDotFrame = $(),
1968
+ $navThumbFrame = $(),
1969
+
1970
+ stageShaftData = $stageShaft.data(),
1971
+ navShaftData = $navShaft.data(),
1972
+
1973
+ $thumbBorder = $(div(thumbBorderClass)).appendTo($navShaft),
1974
+
1975
+ $fullscreenIcon = $(div(fullscreenIconClass + buttonAttributes)),
1976
+ fullscreenIcon = $fullscreenIcon[0],
1977
+ $videoPlay = $(div(videoPlayClass)),
1978
+ $videoClose = $(div(videoCloseClass)).appendTo($stage),
1979
+ videoClose = $videoClose[0],
1980
+
1981
+ spinner,
1982
+ $spinner = $(div(spinnerClass)),
1983
+
1984
+ $videoPlaying,
1985
+
1986
+ activeIndex = false,
1987
+ activeFrame,
1988
+ activeIndexes,
1989
+ repositionIndex,
1990
+ dirtyIndex,
1991
+ lastActiveIndex,
1992
+ prevIndex,
1993
+ nextIndex,
1994
+ nextAutoplayIndex,
1995
+ startIndex,
1996
+
1997
+ o_loop,
1998
+ o_nav,
1999
+ o_navThumbs,
2000
+ o_navTop,
2001
+ o_allowFullScreen,
2002
+ o_nativeFullScreen,
2003
+ o_fade,
2004
+ o_thumbSide,
2005
+ o_thumbSide2,
2006
+ o_transitionDuration,
2007
+ o_transition,
2008
+ o_shadows,
2009
+ o_rtl,
2010
+ o_keyboard,
2011
+ lastOptions = {},
2012
+
2013
+ measures = {},
2014
+ measuresSetFLAG,
2015
+
2016
+ stageShaftTouchTail = {},
2017
+ stageWheelTail = {},
2018
+ navShaftTouchTail = {},
2019
+ navWheelTail = {},
2020
+
2021
+ scrollTop,
2022
+ scrollLeft,
2023
+
2024
+ showedFLAG,
2025
+ pausedAutoplayFLAG,
2026
+ stoppedAutoplayFLAG,
2027
+
2028
+ toDeactivate = {},
2029
+ toDetach = {},
2030
+
2031
+ measuresStash,
2032
+
2033
+ touchedFLAG,
2034
+
2035
+ hoverFLAG,
2036
+
2037
+ navFrameKey,
2038
+ stageLeft = 0,
2039
+
2040
+ fadeStack = [];
2041
+
2042
+ $wrap[STAGE_FRAME_KEY] = $(div(stageFrameClass));
2043
+ $wrap[NAV_THUMB_FRAME_KEY] = $(div(navFrameClass + ' ' + navFrameThumbClass + buttonAttributes, div(thumbClass)));
2044
+ $wrap[NAV_DOT_FRAME_KEY] = $(div(navFrameClass + ' ' + navFrameDotClass + buttonAttributes, div(dotClass)));
2045
+
2046
+ toDeactivate[STAGE_FRAME_KEY] = [];
2047
+ toDeactivate[NAV_THUMB_FRAME_KEY] = [];
2048
+ toDeactivate[NAV_DOT_FRAME_KEY] = [];
2049
+ toDetach[STAGE_FRAME_KEY] = {};
2050
+
2051
+ $wrap
2052
+ .addClass(CSS3 ? wrapCss3Class : wrapCss2Class)
2053
+ .toggleClass(wrapNoControlsClass, !opts.controlsonstart);
2054
+
2055
+ fotoramaData.fotorama = this;
2056
+
2057
+ function checkForVideo () {
2058
+ $.each(data, function (i, dataFrame) {
2059
+ if (!dataFrame.i) {
2060
+ dataFrame.i = dataFrameCount++;
2061
+ var video = findVideoId(dataFrame.video, true);
2062
+ if (video) {
2063
+ var thumbs = {};
2064
+ dataFrame.video = video;
2065
+ if (!dataFrame.img && !dataFrame.thumb) {
2066
+ thumbs = getVideoThumbs(dataFrame, data, that);
2067
+ } else {
2068
+ dataFrame.thumbsReady = true;
2069
+ }
2070
+ updateData(data, {img: thumbs.img, thumb: thumbs.thumb}, dataFrame.i, that);
2071
+ }
2072
+ }
2073
+ });
2074
+ }
2075
+
2076
+ function allowKey (key) {
2077
+ return o_keyboard[key] || that.fullScreen;
2078
+ }
2079
+
2080
+ function bindGlobalEvents (FLAG) {
2081
+ var keydownCommon = 'keydown.' + _fotoramaClass,
2082
+ localStamp = _fotoramaClass + stamp,
2083
+ keydownLocal = 'keydown.' + localStamp,
2084
+ resizeLocal = 'resize.' + localStamp + ' ' + 'orientationchange.' + localStamp;
2085
+
2086
+ if (FLAG) {
2087
+ $DOCUMENT
2088
+ .on(keydownLocal, function (e) {
2089
+ var catched,
2090
+ index;
2091
+
2092
+ if ($videoPlaying && e.keyCode === 27) {
2093
+ catched = true;
2094
+ unloadVideo($videoPlaying, true, true);
2095
+ } else if (that.fullScreen || (opts.keyboard && !that.index)) {
2096
+ if (e.keyCode === 27) {
2097
+ catched = true;
2098
+ that.cancelFullScreen();
2099
+ } else if ((e.shiftKey && e.keyCode === 32 && allowKey('space')) || (e.keyCode === 37 && allowKey('left')) || (e.keyCode === 38 && allowKey('up'))) {
2100
+ index = '<';
2101
+ } else if ((e.keyCode === 32 && allowKey('space')) || (e.keyCode === 39 && allowKey('right')) || (e.keyCode === 40 && allowKey('down'))) {
2102
+ index = '>';
2103
+ } else if (e.keyCode === 36 && allowKey('home')) {
2104
+ index = '<<';
2105
+ } else if (e.keyCode === 35 && allowKey('end')) {
2106
+ index = '>>';
2107
+ }
2108
+ }
2109
+
2110
+ (catched || index) && stopEvent(e);
2111
+ index && that.show({index: index, slow: e.altKey, user: true});
2112
+ });
2113
+
2114
+ if (!that.index) {
2115
+ $DOCUMENT
2116
+ .off(keydownCommon)
2117
+ .on(keydownCommon, 'textarea, input, select', function (e) {
2118
+ !$BODY.hasClass(_fullscreenClass) && e.stopPropagation();
2119
+ });
2120
+ }
2121
+
2122
+ $WINDOW.on(resizeLocal, that.resize);
2123
+ } else {
2124
+ $DOCUMENT.off(keydownLocal);
2125
+ $WINDOW.off(resizeLocal);
2126
+ }
2127
+ }
2128
+
2129
+ function appendElements (FLAG) {
2130
+ if (FLAG === appendElements.f) return;
2131
+
2132
+ if (FLAG) {
2133
+ $fotorama
2134
+ .html('')
2135
+ .addClass(_fotoramaClass + ' ' + stampClass)
2136
+ .append($wrap)
2137
+ .before($style)
2138
+ .before($anchor);
2139
+
2140
+ addInstance(that);
2141
+ } else {
2142
+ $wrap.detach();
2143
+ $style.detach();
2144
+ $anchor.detach();
2145
+ $fotorama
2146
+ .html(fotoramaData.urtext)
2147
+ .removeClass(stampClass);
2148
+
2149
+ hideInstance(that);
2150
+ }
2151
+
2152
+ bindGlobalEvents(FLAG);
2153
+ appendElements.f = FLAG;
2154
+ }
2155
+
2156
+ function setData () {
2157
+ data = that.data = data || clone(opts.data) || getDataFromHtml($fotorama);
2158
+ size = that.size = data.length;
2159
+
2160
+ !ready.ok && opts.shuffle && shuffle(data);
2161
+
2162
+ checkForVideo();
2163
+
2164
+ activeIndex = limitIndex(activeIndex);
2165
+
2166
+ size && appendElements(true);
2167
+ }
2168
+
2169
+ function stageNoMove () {
2170
+ var _noMove = (size < 2 && !opts.enableifsingleframe) || $videoPlaying;
2171
+ stageShaftTouchTail.noMove = _noMove || o_fade;
2172
+ stageShaftTouchTail.noSwipe = _noMove || !opts.swipe;
2173
+
2174
+ !o_transition && $stageShaft.toggleClass(grabClass, !opts.click && !stageShaftTouchTail.noMove && !stageShaftTouchTail.noSwipe);
2175
+ MS_POINTER && $wrap.toggleClass(wrapPanYClass, !stageShaftTouchTail.noSwipe);
2176
+ }
2177
+
2178
+ function setAutoplayInterval (interval) {
2179
+ if (interval === true) interval = '';
2180
+ opts.autoplay = Math.max(+interval || AUTOPLAY_INTERVAL, o_transitionDuration * 1.5);
2181
+ }
2182
+
2183
+ /**
2184
+ * Options on the fly
2185
+ * */
2186
+ function setOptions () {
2187
+ that.options = opts = optionsToLowerCase(opts);
2188
+
2189
+ o_fade = (opts.transition === 'crossfade' || opts.transition === 'dissolve');
2190
+
2191
+ o_loop = opts.loop && (size > 2 || (o_fade && (!o_transition || o_transition !== 'slide')));
2192
+
2193
+ o_transitionDuration = +opts.transitionduration || TRANSITION_DURATION;
2194
+
2195
+ o_rtl = opts.direction === 'rtl';
2196
+
2197
+ o_keyboard = $.extend({}, opts.keyboard && KEYBOARD_OPTIONS, opts.keyboard);
2198
+
2199
+ var classes = {add: [], remove: []};
2200
+
2201
+ function addOrRemoveClass (FLAG, value) {
2202
+ classes[FLAG ? 'add' : 'remove'].push(value);
2203
+ }
2204
+
2205
+ if (size > 1 || opts.enableifsingleframe) {
2206
+ o_nav = opts.nav;
2207
+ o_navTop = opts.navposition === 'top';
2208
+ classes.remove.push(selectClass);
2209
+
2210
+ $arrs.toggle(!!opts.arrows);
2211
+ } else {
2212
+ o_nav = false;
2213
+ $arrs.hide();
2214
+ }
2215
+
2216
+ spinnerStop();
2217
+ spinner = new Spinner($.extend(spinnerDefaults, opts.spinner, spinnerOverride, {direction: o_rtl ? -1 : 1}));
2218
+
2219
+ arrsUpdate();
2220
+ stageWheelUpdate();
2221
+
2222
+ if (opts.autoplay) setAutoplayInterval(opts.autoplay);
2223
+
2224
+ o_thumbSide = numberFromMeasure(opts.thumbwidth) || THUMB_SIZE;
2225
+ o_thumbSide2 = numberFromMeasure(opts.thumbheight) || THUMB_SIZE;
2226
+
2227
+ stageWheelTail.ok = navWheelTail.ok = opts.trackpad && !SLOW;
2228
+
2229
+ stageNoMove();
2230
+
2231
+ extendMeasures(opts, [measures]);
2232
+
2233
+ o_navThumbs = o_nav === 'thumbs';
2234
+
2235
+ if (o_navThumbs) {
2236
+ frameDraw(size, 'navThumb');
2237
+
2238
+ $navFrame = $navThumbFrame;
2239
+ navFrameKey = NAV_THUMB_FRAME_KEY;
2240
+
2241
+ setStyle($style, $.Fotorama.jst.style({w: o_thumbSide, h: o_thumbSide2, b: opts.thumbborderwidth, m: opts.thumbmargin, s: stamp, q: !COMPAT}));
2242
+
2243
+ $nav
2244
+ .addClass(navThumbsClass)
2245
+ .removeClass(navDotsClass);
2246
+ } else if (o_nav === 'dots') {
2247
+ frameDraw(size, 'navDot');
2248
+
2249
+ $navFrame = $navDotFrame;
2250
+ navFrameKey = NAV_DOT_FRAME_KEY;
2251
+
2252
+ $nav
2253
+ .addClass(navDotsClass)
2254
+ .removeClass(navThumbsClass);
2255
+ } else {
2256
+ o_nav = false;
2257
+ $nav.removeClass(navThumbsClass + ' ' + navDotsClass);
2258
+ }
2259
+
2260
+ if (o_nav) {
2261
+ if (o_navTop) {
2262
+ $navWrap.insertBefore($stage);
2263
+ } else {
2264
+ $navWrap.insertAfter($stage);
2265
+ }
2266
+ frameAppend.nav = false;
2267
+ frameAppend($navFrame, $navShaft, 'nav');
2268
+ }
2269
+
2270
+ o_allowFullScreen = opts.allowfullscreen;
2271
+
2272
+ if (o_allowFullScreen) {
2273
+ $fullscreenIcon.prependTo($stage);
2274
+ o_nativeFullScreen = FULLSCREEN && o_allowFullScreen === 'native';
2275
+ } else {
2276
+ $fullscreenIcon.detach();
2277
+ o_nativeFullScreen = false;
2278
+ }
2279
+
2280
+ addOrRemoveClass(o_fade, wrapFadeClass);
2281
+ addOrRemoveClass(!o_fade, wrapSlideClass);
2282
+ addOrRemoveClass(!opts.captions, wrapNoCaptionsClass);
2283
+ addOrRemoveClass(o_rtl, wrapRtlClass);
2284
+ addOrRemoveClass(opts.arrows !== 'always', wrapToggleArrowsClass);
2285
+
2286
+ o_shadows = opts.shadows && !SLOW;
2287
+ addOrRemoveClass(!o_shadows, wrapNoShadowsClass);
2288
+
2289
+ $wrap
2290
+ .addClass(classes.add.join(' '))
2291
+ .removeClass(classes.remove.join(' '));
2292
+
2293
+ lastOptions = $.extend({}, opts);
2294
+ }
2295
+
2296
+ function normalizeIndex (index) {
2297
+ return index < 0 ? (size + (index % size)) % size : index >= size ? index % size : index;
2298
+ }
2299
+
2300
+ function limitIndex (index) {
2301
+ return minMaxLimit(index, 0, size - 1);
2302
+ }
2303
+
2304
+ function edgeIndex (index) {
2305
+ return o_loop ? normalizeIndex(index) : limitIndex(index);
2306
+ }
2307
+
2308
+ function getPrevIndex (index) {
2309
+ return index > 0 || o_loop ? index - 1 : false;
2310
+ }
2311
+
2312
+ function getNextIndex (index) {
2313
+ return index < size - 1 || o_loop ? index + 1 : false;
2314
+ }
2315
+
2316
+ function setStageShaftMinmaxAndSnap () {
2317
+ stageShaftTouchTail.min = o_loop ? -Infinity : -getPosByIndex(size - 1, measures.w, opts.margin, repositionIndex);
2318
+ stageShaftTouchTail.max = o_loop ? Infinity : -getPosByIndex(0, measures.w, opts.margin, repositionIndex);
2319
+ stageShaftTouchTail.snap = measures.w + opts.margin;
2320
+ }
2321
+
2322
+ function setNavShaftMinMax () {
2323
+ //////console.log('setNavShaftMinMax', measures.nw);
2324
+ navShaftTouchTail.min = Math.min(0, measures.nw - $navShaft.width());
2325
+ navShaftTouchTail.max = 0;
2326
+ $navShaft.toggleClass(grabClass, !(navShaftTouchTail.noMove = navShaftTouchTail.min === navShaftTouchTail.max));
2327
+ }
2328
+
2329
+ function eachIndex (indexes, type, fn) {
2330
+ if (typeof indexes === 'number') {
2331
+ indexes = new Array(indexes);
2332
+ var rangeFLAG = true;
2333
+ }
2334
+ return $.each(indexes, function (i, index) {
2335
+ if (rangeFLAG) index = i;
2336
+ if (typeof index === 'number') {
2337
+ var dataFrame = data[normalizeIndex(index)];
2338
+
2339
+ if (dataFrame) {
2340
+ var key = '$' + type + 'Frame',
2341
+ $frame = dataFrame[key];
2342
+
2343
+ fn.call(this, i, index, dataFrame, $frame, key, $frame && $frame.data());
2344
+ }
2345
+ }
2346
+ });
2347
+ }
2348
+
2349
+ function setMeasures (width, height, ratio, index) {
2350
+ if (!measuresSetFLAG || (measuresSetFLAG === '*' && index === startIndex)) {
2351
+
2352
+ ////console.log('setMeasures', index, opts.width, opts.height);
2353
+
2354
+ width = measureIsValid(opts.width) || measureIsValid(width) || WIDTH;
2355
+ height = measureIsValid(opts.height) || measureIsValid(height) || HEIGHT;
2356
+ that.resize({
2357
+ width: width,
2358
+ ratio: opts.ratio || ratio || width / height
2359
+ }, 0, index !== startIndex && '*');
2360
+ }
2361
+ }
2362
+
2363
+ function loadImg (indexes, type, specialMeasures, method, position, again) {
2364
+ eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) {
2365
+
2366
+ if (!$frame) return;
2367
+
2368
+ var fullFLAG = that.fullScreen && dataFrame.full && dataFrame.full !== dataFrame.img && !frameData.$full && type === 'stage';
2369
+
2370
+ if (frameData.$img && !again && !fullFLAG) return;
2371
+
2372
+ var img = new Image(),
2373
+ $img = $(img),
2374
+ imgData = $img.data();
2375
+
2376
+ frameData[fullFLAG ? '$full' : '$img'] = $img;
2377
+
2378
+ var srcKey = type === 'stage' ? (fullFLAG ? 'full' : 'img') : 'thumb',
2379
+ src = dataFrame[srcKey],
2380
+ dummy = fullFLAG ? null : dataFrame[type === 'stage' ? 'thumb' : 'img'];
2381
+
2382
+ if (type === 'navThumb') $frame = frameData.$wrap;
2383
+
2384
+ function triggerTriggerEvent (event) {
2385
+ var _index = normalizeIndex(index);
2386
+ triggerEvent(event, {
2387
+ index: _index,
2388
+ src: src,
2389
+ frame: data[_index]
2390
+ });
2391
+ }
2392
+
2393
+ function error () {
2394
+ $img.remove();
2395
+
2396
+ $.Fotorama.cache[src] = 'error';
2397
+
2398
+ if ((!dataFrame.html || type !== 'stage') && dummy && dummy !== src) {
2399
+ dataFrame[srcKey] = src = dummy;
2400
+ loadImg([index], type, specialMeasures, method, position, true);
2401
+ } else {
2402
+ if (src && !dataFrame.html && !fullFLAG) {
2403
+ $frame
2404
+ .trigger('f:error')
2405
+ .removeClass(loadingClass)
2406
+ .addClass(errorClass);
2407
+
2408
+ triggerTriggerEvent('error');
2409
+ } else if (type === 'stage') {
2410
+ $frame
2411
+ .trigger('f:load')
2412
+ .removeClass(loadingClass + ' ' + errorClass)
2413
+ .addClass(loadedClass);
2414
+
2415
+ triggerTriggerEvent('load');
2416
+ setMeasures();
2417
+ }
2418
+
2419
+ frameData.state = 'error';
2420
+
2421
+ if (size > 1 && data[index] === dataFrame && !dataFrame.html && !dataFrame.deleted && !dataFrame.video && !fullFLAG) {
2422
+ dataFrame.deleted = true;
2423
+ that.splice(index, 1);
2424
+ }
2425
+ }
2426
+ }
2427
+
2428
+ function loaded () {
2429
+ ////console.log('loaded: ' + src);
2430
+
2431
+ //console.log('$.Fotorama.measures[src]', $.Fotorama.measures[src]);
2432
+
2433
+ $.Fotorama.measures[src] = imgData.measures = $.Fotorama.measures[src] || {
2434
+ width: img.width,
2435
+ height: img.height,
2436
+ ratio: img.width / img.height
2437
+ };
2438
+
2439
+ setMeasures(imgData.measures.width, imgData.measures.height, imgData.measures.ratio, index);
2440
+
2441
+ $img
2442
+ .off('load error')
2443
+ .addClass(imgClass + (fullFLAG ? ' ' + imgFullClass : ''))
2444
+ .prependTo($frame);
2445
+
2446
+ fit($img, ($.isFunction(specialMeasures) ? specialMeasures() : specialMeasures) || measures, method || dataFrame.fit || opts.fit, position || dataFrame.position || opts.position);
2447
+
2448
+ $.Fotorama.cache[src] = frameData.state = 'loaded';
2449
+
2450
+ setTimeout(function () {
2451
+ $frame
2452
+ .trigger('f:load')
2453
+ .removeClass(loadingClass + ' ' + errorClass)
2454
+ .addClass(loadedClass + ' ' + (fullFLAG ? loadedFullClass : loadedImgClass));
2455
+
2456
+ if (type === 'stage') {
2457
+ triggerTriggerEvent('load');
2458
+ } else if (dataFrame.thumbratio === AUTO || !dataFrame.thumbratio && opts.thumbratio === AUTO) {
2459
+ // danger! reflow for all thumbnails
2460
+ dataFrame.thumbratio = imgData.measures.ratio;
2461
+ reset();
2462
+ }
2463
+ }, 0);
2464
+ }
2465
+
2466
+ if (!src) {
2467
+ error();
2468
+ return;
2469
+ }
2470
+
2471
+ function waitAndLoad () {
2472
+ var _i = 10;
2473
+ waitFor(function () {
2474
+ return !touchedFLAG || !_i-- && !SLOW;
2475
+ }, function () {
2476
+ loaded();
2477
+ });
2478
+ }
2479
+
2480
+ if (!$.Fotorama.cache[src]) {
2481
+ $.Fotorama.cache[src] = '*';
2482
+
2483
+ $img
2484
+ .on('load', waitAndLoad)
2485
+ .on('error', error);
2486
+ } else {
2487
+ (function justWait () {
2488
+ if ($.Fotorama.cache[src] === 'error') {
2489
+ error();
2490
+ } else if ($.Fotorama.cache[src] === 'loaded') {
2491
+ //console.log('take from cache: ' + src);
2492
+ setTimeout(waitAndLoad, 0);
2493
+ } else {
2494
+ setTimeout(justWait, 100);
2495
+ }
2496
+ })();
2497
+ }
2498
+
2499
+ frameData.state = '';
2500
+ img.src = src;
2501
+ });
2502
+ }
2503
+
2504
+ function spinnerSpin ($el) {
2505
+ $spinner.append(spinner.spin().el).appendTo($el);
2506
+ }
2507
+
2508
+ function spinnerStop () {
2509
+ $spinner.detach();
2510
+ spinner && spinner.stop();
2511
+ }
2512
+
2513
+ function updateFotoramaState () {
2514
+ var $frame = activeFrame[STAGE_FRAME_KEY];
2515
+
2516
+ if ($frame && !$frame.data().state) {
2517
+ spinnerSpin($frame);
2518
+ $frame.on('f:load f:error', function () {
2519
+ $frame.off('f:load f:error');
2520
+ spinnerStop();
2521
+ });
2522
+ }
2523
+ }
2524
+
2525
+ function addNavFrameEvents (frame) {
2526
+ addEnterUp(frame, onNavFrameClick);
2527
+ addFocus(frame, function () {
2528
+
2529
+ setTimeout(function () {
2530
+ lockScroll($nav);
2531
+ }, 0);
2532
+ slideNavShaft({time: o_transitionDuration, guessIndex: $(this).data().eq, minMax: navShaftTouchTail});
2533
+ });
2534
+ }
2535
+
2536
+ function frameDraw (indexes, type) {
2537
+ eachIndex(indexes, type, function (i, index, dataFrame, $frame, key, frameData) {
2538
+ if ($frame) return;
2539
+
2540
+ $frame = dataFrame[key] = $wrap[key].clone();
2541
+ frameData = $frame.data();
2542
+ frameData.data = dataFrame;
2543
+ var frame = $frame[0];
2544
+
2545
+ if (type === 'stage') {
2546
+
2547
+ if (dataFrame.html) {
2548
+ $('<div class="' + htmlClass + '"></div>')
2549
+ .append(
2550
+ dataFrame._html ? $(dataFrame.html)
2551
+ .removeAttr('id')
2552
+ .html(dataFrame._html) // Because of IE
2553
+ : dataFrame.html
2554
+ )
2555
+ .appendTo($frame);
2556
+ }
2557
+
2558
+ dataFrame.caption && $(div(captionClass, div(captionWrapClass, dataFrame.caption))).appendTo($frame);
2559
+
2560
+ dataFrame.video && $frame
2561
+ .addClass(stageFrameVideoClass)
2562
+ .append($videoPlay.clone());
2563
+
2564
+ // This solves tabbing problems
2565
+ addFocus(frame, function () {
2566
+ setTimeout(function () {
2567
+ lockScroll($stage);
2568
+ }, 0);
2569
+ clickToShow({index: frameData.eq, user: true});
2570
+ });
2571
+
2572
+ $stageFrame = $stageFrame.add($frame);
2573
+ } else if (type === 'navDot') {
2574
+ addNavFrameEvents(frame);
2575
+ $navDotFrame = $navDotFrame.add($frame);
2576
+ } else if (type === 'navThumb') {
2577
+ addNavFrameEvents(frame);
2578
+ frameData.$wrap = $frame.children(':first');
2579
+ $navThumbFrame = $navThumbFrame.add($frame);
2580
+ if (dataFrame.video) {
2581
+ frameData.$wrap.append($videoPlay.clone());
2582
+ }
2583
+ }
2584
+ });
2585
+ }
2586
+
2587
+ function callFit ($img, measuresToFit, method, position) {
2588
+ return $img && $img.length && fit($img, measuresToFit, method, position);
2589
+ }
2590
+
2591
+ function stageFramePosition (indexes) {
2592
+ eachIndex(indexes, 'stage', function (i, index, dataFrame, $frame, key, frameData) {
2593
+ if (!$frame) return;
2594
+
2595
+ var normalizedIndex = normalizeIndex(index),
2596
+ method = dataFrame.fit || opts.fit,
2597
+ position = dataFrame.position || opts.position;
2598
+ frameData.eq = normalizedIndex;
2599
+
2600
+ toDetach[STAGE_FRAME_KEY][normalizedIndex] = $frame.css($.extend({left: o_fade ? 0 : getPosByIndex(index, measures.w, opts.margin, repositionIndex)}, o_fade && getDuration(0)));
2601
+
2602
+ if (isDetached($frame[0])) {
2603
+ $frame.appendTo($stageShaft);
2604
+ unloadVideo(dataFrame.$video);
2605
+ }
2606
+
2607
+ callFit(frameData.$img, measures, method, position);
2608
+ callFit(frameData.$full, measures, method, position);
2609
+ });
2610
+ }
2611
+
2612
+ function thumbsDraw (pos, loadFLAG) {
2613
+ if (o_nav !== 'thumbs' || isNaN(pos)) return;
2614
+
2615
+ var leftLimit = -pos,
2616
+ rightLimit = -pos + measures.nw;
2617
+
2618
+ $navThumbFrame.each(function () {
2619
+ var $this = $(this),
2620
+ thisData = $this.data(),
2621
+ eq = thisData.eq,
2622
+ getSpecialMeasures = function () {
2623
+ return {
2624
+ h: o_thumbSide2,
2625
+ w: thisData.w
2626
+ }
2627
+ },
2628
+ specialMeasures = getSpecialMeasures(),
2629
+ dataFrame = data[eq] || {},
2630
+ method = dataFrame.thumbfit || opts.thumbfit,
2631
+ position = dataFrame.thumbposition || opts.thumbposition;
2632
+
2633
+ specialMeasures.w = thisData.w;
2634
+
2635
+ if (thisData.l + thisData.w < leftLimit
2636
+ || thisData.l > rightLimit
2637
+ || callFit(thisData.$img, specialMeasures, method, position)) return;
2638
+
2639
+ loadFLAG && loadImg([eq], 'navThumb', getSpecialMeasures, method, position);
2640
+ });
2641
+ }
2642
+
2643
+ function frameAppend ($frames, $shaft, type) {
2644
+ if (!frameAppend[type]) {
2645
+
2646
+ var thumbsFLAG = type === 'nav' && o_navThumbs,
2647
+ left = 0;
2648
+
2649
+ $shaft.append(
2650
+ $frames
2651
+ .filter(function () {
2652
+ var actual,
2653
+ $this = $(this),
2654
+ frameData = $this.data();
2655
+ for (var _i = 0, _l = data.length; _i < _l; _i++) {
2656
+ if (frameData.data === data[_i]) {
2657
+ actual = true;
2658
+ frameData.eq = _i;
2659
+ break;
2660
+ }
2661
+ }
2662
+ return actual || $this.remove() && false;
2663
+ })
2664
+ .sort(function (a, b) {
2665
+ return $(a).data().eq - $(b).data().eq;
2666
+ })
2667
+ .each(function () {
2668
+
2669
+ if (!thumbsFLAG) return;
2670
+
2671
+ var $this = $(this),
2672
+ frameData = $this.data(),
2673
+ thumbwidth = Math.round(o_thumbSide2 * frameData.data.thumbratio) || o_thumbSide;
2674
+
2675
+ frameData.l = left;
2676
+ frameData.w = thumbwidth;
2677
+
2678
+ $this.css({width: thumbwidth});
2679
+
2680
+ left += thumbwidth + opts.thumbmargin;
2681
+ })
2682
+ );
2683
+
2684
+ frameAppend[type] = true;
2685
+ }
2686
+ }
2687
+
2688
+ function getDirection (x) {
2689
+ return x - stageLeft > measures.w / 3;
2690
+ }
2691
+
2692
+ function disableDirrection (i) {
2693
+ return !o_loop && (!(activeIndex + i) || !(activeIndex - size + i)) && !$videoPlaying;
2694
+ }
2695
+
2696
+ function arrsUpdate () {
2697
+ var disablePrev = disableDirrection(0),
2698
+ disableNext = disableDirrection(1);
2699
+ $arrPrev
2700
+ .toggleClass(arrDisabledClass, disablePrev)
2701
+ .attr(disableAttr(disablePrev));
2702
+ $arrNext
2703
+ .toggleClass(arrDisabledClass, disableNext)
2704
+ .attr(disableAttr(disableNext));
2705
+ }
2706
+
2707
+ function stageWheelUpdate () {
2708
+ if (stageWheelTail.ok) {
2709
+ stageWheelTail.prevent = {'<': disableDirrection(0), '>': disableDirrection(1)};
2710
+ }
2711
+ }
2712
+
2713
+ function getNavFrameBounds ($navFrame) {
2714
+ var navFrameData = $navFrame.data(),
2715
+ left,
2716
+ width;
2717
+
2718
+ if (o_navThumbs) {
2719
+ left = navFrameData.l;
2720
+ width = navFrameData.w;
2721
+ } else {
2722
+ left = $navFrame.position().left;
2723
+ width = $navFrame.width();
2724
+ }
2725
+
2726
+ return {
2727
+ c: left + width / 2,
2728
+ min: -left + opts.thumbmargin * 10,
2729
+ max: -left + measures.w - width - opts.thumbmargin * 10
2730
+ };
2731
+ }
2732
+
2733
+ function slideThumbBorder (time) {
2734
+ var navFrameData = activeFrame[navFrameKey].data();
2735
+ slide($thumbBorder, {
2736
+ time: time * 1.2,
2737
+ pos: navFrameData.l,
2738
+ width: navFrameData.w - opts.thumbborderwidth * 2
2739
+ });
2740
+ }
2741
+
2742
+ function slideNavShaft (options) {
2743
+ //console.log('slideNavShaft', options.guessIndex, options.keep, slideNavShaft.l);
2744
+ var $guessNavFrame = data[options.guessIndex][navFrameKey];
2745
+ if ($guessNavFrame) {
2746
+ var overflowFLAG = navShaftTouchTail.min !== navShaftTouchTail.max,
2747
+ minMax = options.minMax || overflowFLAG && getNavFrameBounds(activeFrame[navFrameKey]),
2748
+ l = overflowFLAG && (options.keep && slideNavShaft.l ? slideNavShaft.l : minMaxLimit((options.coo || measures.nw / 2) - getNavFrameBounds($guessNavFrame).c, minMax.min, minMax.max)),
2749
+ pos = overflowFLAG && minMaxLimit(l, navShaftTouchTail.min, navShaftTouchTail.max),
2750
+ time = options.time * 1.1;
2751
+
2752
+ slide($navShaft, {
2753
+ time: time,
2754
+ pos: pos || 0,
2755
+ onEnd: function () {
2756
+ thumbsDraw(pos, true);
2757
+ }
2758
+ });
2759
+
2760
+ //if (time) thumbsDraw(pos);
2761
+
2762
+ setShadow($nav, findShadowEdge(pos, navShaftTouchTail.min, navShaftTouchTail.max));
2763
+ slideNavShaft.l = l;
2764
+ }
2765
+ }
2766
+
2767
+ function navUpdate () {
2768
+ deactivateFrames(navFrameKey);
2769
+ toDeactivate[navFrameKey].push(activeFrame[navFrameKey].addClass(activeClass));
2770
+ }
2771
+
2772
+ function deactivateFrames (key) {
2773
+ var _toDeactivate = toDeactivate[key];
2774
+
2775
+ while (_toDeactivate.length) {
2776
+ _toDeactivate.shift().removeClass(activeClass);
2777
+ }
2778
+ }
2779
+
2780
+ function detachFrames (key) {
2781
+ var _toDetach = toDetach[key];
2782
+
2783
+ ////console.log('_toDetach', _toDetach);
2784
+ ////console.log('activeIndexes', activeIndexes);
2785
+
2786
+ $.each(activeIndexes, function (i, index) {
2787
+ delete _toDetach[normalizeIndex(index)];
2788
+ });
2789
+
2790
+ $.each(_toDetach, function (index, $frame) {
2791
+ delete _toDetach[index];
2792
+ ////console.log('Detach', index);
2793
+ $frame.detach();
2794
+ });
2795
+ }
2796
+
2797
+ function stageShaftReposition (skipOnEnd) {
2798
+
2799
+ repositionIndex = dirtyIndex = activeIndex;
2800
+
2801
+ var $frame = activeFrame[STAGE_FRAME_KEY];
2802
+
2803
+ if ($frame) {
2804
+ deactivateFrames(STAGE_FRAME_KEY);
2805
+ toDeactivate[STAGE_FRAME_KEY].push($frame.addClass(activeClass));
2806
+
2807
+ skipOnEnd || that.show.onEnd(true);
2808
+ stop($stageShaft, 0, true);
2809
+
2810
+ detachFrames(STAGE_FRAME_KEY);
2811
+ stageFramePosition(activeIndexes);
2812
+ setStageShaftMinmaxAndSnap();
2813
+ setNavShaftMinMax();
2814
+ }
2815
+ }
2816
+
2817
+ function extendMeasures (options, measuresArray) {
2818
+ if (!options) return;
2819
+
2820
+ $.each(measuresArray, function (i, measures) {
2821
+ if (!measures) return;
2822
+
2823
+ $.extend(measures, {
2824
+ width: options.width || measures.width,
2825
+ height: options.height,
2826
+ minwidth: options.minwidth,
2827
+ maxwidth: options.maxwidth,
2828
+ minheight: options.minheight,
2829
+ maxheight: options.maxheight,
2830
+ ratio: getRatio(options.ratio)
2831
+ })
2832
+ });
2833
+ }
2834
+
2835
+ function triggerEvent (event, extra) {
2836
+ $fotorama.trigger(_fotoramaClass + ':' + event, [that, extra]);
2837
+ }
2838
+
2839
+ function onTouchStart () {
2840
+ clearTimeout(onTouchEnd.t);
2841
+ touchedFLAG = 1;
2842
+
2843
+ if (opts.stopautoplayontouch) {
2844
+ that.stopAutoplay();
2845
+ } else {
2846
+ pausedAutoplayFLAG = true;
2847
+ }
2848
+ }
2849
+
2850
+ function onTouchEnd () {
2851
+ if (!touchedFLAG) return;
2852
+ if (!opts.stopautoplayontouch) {
2853
+ releaseAutoplay();
2854
+ changeAutoplay();
2855
+ }
2856
+
2857
+ onTouchEnd.t = setTimeout(function () {
2858
+ touchedFLAG = 0;
2859
+ }, TRANSITION_DURATION + TOUCH_TIMEOUT);
2860
+ ////console.timeEnd('onTouchEnd');
2861
+ }
2862
+
2863
+ function releaseAutoplay () {
2864
+ //console.log('releaseAutoplay');
2865
+ pausedAutoplayFLAG = !!($videoPlaying || stoppedAutoplayFLAG);
2866
+ }
2867
+
2868
+ function changeAutoplay () {
2869
+ //console.log('changeAutoplay');
2870
+
2871
+ clearTimeout(changeAutoplay.t);
2872
+ waitFor.stop(changeAutoplay.w);
2873
+
2874
+ if (!opts.autoplay || pausedAutoplayFLAG) {
2875
+ if (that.autoplay) {
2876
+ that.autoplay = false;
2877
+ triggerEvent('stopautoplay');
2878
+ }
2879
+
2880
+ return;
2881
+ }
2882
+
2883
+ //console.log('changeAutoplay continue');
2884
+
2885
+ if (!that.autoplay) {
2886
+ that.autoplay = true;
2887
+ triggerEvent('startautoplay');
2888
+ }
2889
+
2890
+ var _activeIndex = activeIndex;
2891
+
2892
+
2893
+ var frameData = activeFrame[STAGE_FRAME_KEY].data();
2894
+ changeAutoplay.w = waitFor(function () {
2895
+ //console.log('wait for the state of the current frame');
2896
+ return frameData.state || _activeIndex !== activeIndex;
2897
+ }, function () {
2898
+ //console.log('the current frame is ready');
2899
+ changeAutoplay.t = setTimeout(function () {
2900
+ //console.log('changeAutoplay.t setTimeout', pausedAutoplayFLAG, _activeIndex !== activeIndex);
2901
+ if (pausedAutoplayFLAG || _activeIndex !== activeIndex) return;
2902
+
2903
+ var _nextAutoplayIndex = nextAutoplayIndex,
2904
+ nextFrameData = data[_nextAutoplayIndex][STAGE_FRAME_KEY].data();
2905
+
2906
+ changeAutoplay.w = waitFor(function () {
2907
+ //console.log('wait for the state of the next frame');
2908
+ return nextFrameData.state || _nextAutoplayIndex !== nextAutoplayIndex;
2909
+ }, function () {
2910
+ if (pausedAutoplayFLAG || _nextAutoplayIndex !== nextAutoplayIndex) return;
2911
+ that.show(o_loop ? getDirectionSign(!o_rtl) : nextAutoplayIndex);
2912
+ });
2913
+ }, opts.autoplay);
2914
+ });
2915
+
2916
+ }
2917
+
2918
+ that.startAutoplay = function (interval) {
2919
+ if (that.autoplay) return this;
2920
+ pausedAutoplayFLAG = stoppedAutoplayFLAG = false;
2921
+ setAutoplayInterval(interval || opts.autoplay);
2922
+ changeAutoplay();
2923
+
2924
+ return this;
2925
+ };
2926
+
2927
+ that.stopAutoplay = function () {
2928
+ if (that.autoplay) {
2929
+ pausedAutoplayFLAG = stoppedAutoplayFLAG = true;
2930
+ changeAutoplay();
2931
+ }
2932
+ return this;
2933
+ };
2934
+
2935
+ that.show = function (options) {
2936
+ //console.log('that.show');
2937
+ ////console.time('that.show prepare');
2938
+ var index;
2939
+
2940
+ if (typeof options !== 'object') {
2941
+ index = options;
2942
+ options = {};
2943
+ } else {
2944
+ index = options.index;
2945
+ }
2946
+
2947
+ index = index === '>' ? dirtyIndex + 1 : index === '<' ? dirtyIndex - 1 : index === '<<' ? 0 : index === '>>' ? size - 1 : index;
2948
+ index = isNaN(index) ? getIndexFromHash(index, data, true) : index;
2949
+ index = typeof index === 'undefined' ? activeIndex || 0 : index;
2950
+
2951
+ that.activeIndex = activeIndex = edgeIndex(index);
2952
+ prevIndex = getPrevIndex(activeIndex);
2953
+ nextIndex = getNextIndex(activeIndex);
2954
+ nextAutoplayIndex = normalizeIndex(activeIndex + (o_rtl ? -1 : 1));
2955
+ activeIndexes = [activeIndex, prevIndex, nextIndex];
2956
+
2957
+ dirtyIndex = o_loop ? index : activeIndex;
2958
+
2959
+ var diffIndex = Math.abs(lastActiveIndex - dirtyIndex),
2960
+ time = getNumber(options.time, function () {
2961
+ return Math.min(o_transitionDuration * (1 + (diffIndex - 1) / 12), o_transitionDuration * 2);
2962
+ }),
2963
+ overPos = options.overPos;
2964
+
2965
+ if (options.slow) time *= 10;
2966
+
2967
+ var _activeFrame = activeFrame;
2968
+ that.activeFrame = activeFrame = data[activeIndex];
2969
+ ////console.timeEnd('that.show prepare');
2970
+
2971
+ var silent = _activeFrame === activeFrame && !options.user;
2972
+
2973
+ //setTimeout(function () {
2974
+ ////console.time('unloadVideo');
2975
+ unloadVideo($videoPlaying, activeFrame.i !== data[normalizeIndex(repositionIndex)].i);
2976
+ ////console.timeEnd('unloadVideo');
2977
+ ////console.time('frameDraw');
2978
+ frameDraw(activeIndexes, 'stage');
2979
+ ////console.timeEnd('frameDraw');
2980
+ ////console.time('stageFramePosition');
2981
+ stageFramePosition(SLOW ? [dirtyIndex] : [dirtyIndex, getPrevIndex(dirtyIndex), getNextIndex(dirtyIndex)]);
2982
+ ////console.timeEnd('stageFramePosition');
2983
+ ////console.time('updateTouchTails');
2984
+ updateTouchTails('go', true);
2985
+ ////console.timeEnd('updateTouchTails');
2986
+ ////console.time('triggerEvent');
2987
+
2988
+ silent || triggerEvent('show', {
2989
+ user: options.user,
2990
+ time: time
2991
+ });
2992
+ ////console.timeEnd('triggerEvent');
2993
+ //}, 0);
2994
+
2995
+ ////console.time('bind onEnd');
2996
+
2997
+ pausedAutoplayFLAG = true;
2998
+
2999
+ var onEnd = that.show.onEnd = function (skipReposition) {
3000
+ if (onEnd.ok) return;
3001
+ onEnd.ok = true;
3002
+
3003
+ skipReposition || stageShaftReposition(true);
3004
+
3005
+ if (!silent) {
3006
+ triggerEvent('showend', {
3007
+ user: options.user
3008
+ });
3009
+ }
3010
+
3011
+ //console.log('o_transition', o_transition);
3012
+
3013
+ if (!skipReposition && o_transition && o_transition !== opts.transition) {
3014
+ //console.log('set transition back to: ' + o_transition);
3015
+ that.setOptions({transition: o_transition});
3016
+ o_transition = false;
3017
+ return;
3018
+ }
3019
+
3020
+ updateFotoramaState();
3021
+ loadImg(activeIndexes, 'stage');
3022
+
3023
+ updateTouchTails('go', false);
3024
+ stageWheelUpdate();
3025
+
3026
+ stageCursor();
3027
+ releaseAutoplay();
3028
+ changeAutoplay();
3029
+ };
3030
+ ////console.timeEnd('bind onEnd');
3031
+
3032
+ if (!o_fade) {
3033
+ ////console.time('slide');
3034
+ slide($stageShaft, {
3035
+ pos: -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex),
3036
+ overPos: overPos,
3037
+ time: time,
3038
+ onEnd: onEnd/*,
3039
+ _001: true*/
3040
+ });
3041
+ ////console.timeEnd('slide');
3042
+ } else {
3043
+ var $activeFrame = activeFrame[STAGE_FRAME_KEY],
3044
+ $prevActiveFrame = activeIndex !== lastActiveIndex ? data[lastActiveIndex][STAGE_FRAME_KEY] : null;
3045
+
3046
+ fade($activeFrame, $prevActiveFrame, $stageFrame, {
3047
+ time: time,
3048
+ method: opts.transition,
3049
+ onEnd: onEnd
3050
+ }, fadeStack);
3051
+ }
3052
+
3053
+ ////console.time('arrsUpdate');
3054
+ arrsUpdate();
3055
+ ////console.timeEnd('arrsUpdate');
3056
+
3057
+ if (o_nav) {
3058
+ ////console.time('navUpdate');
3059
+ navUpdate();
3060
+ ////console.timeEnd('navUpdate');
3061
+
3062
+ ////console.time('slideNavShaft');
3063
+ var guessIndex = limitIndex(activeIndex + minMaxLimit(dirtyIndex - lastActiveIndex, -1, 1));
3064
+ slideNavShaft({time: time, coo: guessIndex !== activeIndex && options.coo, guessIndex: typeof options.coo !== 'undefined' ? guessIndex : activeIndex, keep: silent});
3065
+ ////console.timeEnd('slideNavShaft');
3066
+
3067
+ ////console.time('slideThumbBorder');
3068
+ if (o_navThumbs) slideThumbBorder(time);
3069
+ ////console.timeEnd('slideThumbBorder');
3070
+ }
3071
+
3072
+ ////console.time('that.show end');
3073
+ showedFLAG = typeof lastActiveIndex !== 'undefined' && lastActiveIndex !== activeIndex;
3074
+ lastActiveIndex = activeIndex;
3075
+ opts.hash && showedFLAG && !that.eq && setHash(activeFrame.id || activeIndex + 1);
3076
+ ////console.timeEnd('that.show end');
3077
+
3078
+ ////console.timeEnd('that.show');
3079
+
3080
+ return this;
3081
+ };
3082
+
3083
+ that.requestFullScreen = function () {
3084
+ if (o_allowFullScreen && !that.fullScreen) {
3085
+ scrollTop = $WINDOW.scrollTop();
3086
+ scrollLeft = $WINDOW.scrollLeft();
3087
+
3088
+ lockScroll($WINDOW);
3089
+
3090
+ updateTouchTails('x', true);
3091
+
3092
+ measuresStash = $.extend({}, measures);
3093
+
3094
+ $fotorama
3095
+ .addClass(fullscreenClass)
3096
+ .appendTo($BODY.addClass(_fullscreenClass));
3097
+
3098
+ $HTML.addClass(_fullscreenClass);
3099
+
3100
+ unloadVideo($videoPlaying, true, true);
3101
+
3102
+ that.fullScreen = true;
3103
+
3104
+ if (o_nativeFullScreen) {
3105
+ fullScreenApi.request(fotorama);
3106
+ }
3107
+
3108
+ that.resize();
3109
+ loadImg(activeIndexes, 'stage');
3110
+ updateFotoramaState();
3111
+
3112
+ triggerEvent('fullscreenenter');
3113
+ }
3114
+
3115
+ return this;
3116
+ };
3117
+
3118
+ function cancelFullScreen () {
3119
+ if (that.fullScreen) {
3120
+ that.fullScreen = false;
3121
+
3122
+ if (FULLSCREEN) {
3123
+ fullScreenApi.cancel(fotorama);
3124
+ }
3125
+
3126
+ $BODY.removeClass(_fullscreenClass);
3127
+ $HTML.removeClass(_fullscreenClass);
3128
+
3129
+ $fotorama
3130
+ .removeClass(fullscreenClass)
3131
+ .insertAfter($anchor);
3132
+
3133
+ measures = $.extend({}, measuresStash);
3134
+
3135
+ unloadVideo($videoPlaying, true, true);
3136
+
3137
+ updateTouchTails('x', false);
3138
+
3139
+ that.resize();
3140
+ loadImg(activeIndexes, 'stage');
3141
+
3142
+ lockScroll($WINDOW, scrollLeft, scrollTop);
3143
+
3144
+ triggerEvent('fullscreenexit');
3145
+ }
3146
+ }
3147
+
3148
+ that.cancelFullScreen = function () {
3149
+ if (o_nativeFullScreen && fullScreenApi.is()) {
3150
+ fullScreenApi.cancel(document);
3151
+ } else {
3152
+ cancelFullScreen();
3153
+ }
3154
+
3155
+ return this;
3156
+ };
3157
+
3158
+ that.toggleFullScreen = function () {
3159
+ return that[(that.fullScreen ? 'cancel' : 'request') + 'FullScreen']();
3160
+ };
3161
+
3162
+ addEvent(document, fullScreenApi.event, function () {
3163
+ if (data && !fullScreenApi.is() && !$videoPlaying) {
3164
+ cancelFullScreen();
3165
+ }
3166
+ });
3167
+
3168
+ that.resize = function (options) {
3169
+ if (!data) return this;
3170
+
3171
+ var time = arguments[1] || 0,
3172
+ setFLAG = arguments[2];
3173
+
3174
+ extendMeasures(!that.fullScreen ? optionsToLowerCase(options) : {width: '100%', maxwidth: null, minwidth: null, height: '100%', maxheight: null, minheight: null}, [measures, setFLAG || that.fullScreen || opts]);
3175
+
3176
+ var width = measures.width,
3177
+ height = measures.height,
3178
+ ratio = measures.ratio,
3179
+ windowHeight = $WINDOW.height() - (o_nav ? $nav.height() : 0);
3180
+
3181
+ if (measureIsValid(width)) {
3182
+ $wrap
3183
+ .addClass(wrapOnlyActiveClass)
3184
+ .css({width: width, minWidth: measures.minwidth || 0, maxWidth: measures.maxwidth || MAX_WIDTH});
3185
+
3186
+ width = measures.W = measures.w = $wrap.width();
3187
+ measures.nw = o_nav && numberFromWhatever(opts.navwidth, width) || width;
3188
+
3189
+ if (opts.glimpse) {
3190
+ // Glimpse
3191
+ measures.w -= Math.round((numberFromWhatever(opts.glimpse, width) || 0) * 2);
3192
+ }
3193
+
3194
+ $stageShaft.css({width: measures.w, marginLeft: (measures.W - measures.w) / 2});
3195
+
3196
+ ////console.log('measures.W', measures.W);
3197
+ ////console.log('measures.w', measures.w);
3198
+
3199
+ height = numberFromWhatever(height, windowHeight);
3200
+
3201
+ height = height || (ratio && width / ratio);
3202
+
3203
+ if (height) {
3204
+ width = Math.round(width);
3205
+ height = measures.h = Math.round(minMaxLimit(height, numberFromWhatever(measures.minheight, windowHeight), numberFromWhatever(measures.maxheight, windowHeight)));
3206
+
3207
+ $stage
3208
+ .stop()
3209
+ .animate({width: width, height: height}, time, function () {
3210
+ $wrap.removeClass(wrapOnlyActiveClass);
3211
+ });
3212
+
3213
+ stageShaftReposition();
3214
+
3215
+ if (o_nav) {
3216
+ $nav
3217
+ .stop()
3218
+ .animate({width: measures.nw}, time);
3219
+
3220
+ slideNavShaft({guessIndex: activeIndex, time: time, keep: true});
3221
+ if (o_navThumbs && frameAppend.nav) slideThumbBorder(time);
3222
+ }
3223
+
3224
+ measuresSetFLAG = setFLAG || true;
3225
+
3226
+ ready();
3227
+ }
3228
+ }
3229
+
3230
+ stageLeft = $stage.offset().left;
3231
+
3232
+ return this;
3233
+ };
3234
+
3235
+ that.setOptions = function (options) {
3236
+ $.extend(opts, options);
3237
+ reset();
3238
+ return this;
3239
+ };
3240
+
3241
+ that.shuffle = function () {
3242
+ data && shuffle(data) && reset();
3243
+ return this;
3244
+ };
3245
+
3246
+ function setShadow ($el, edge) {
3247
+ ////console.time('setShadow');
3248
+ if (o_shadows) {
3249
+ $el.removeClass(shadowsLeftClass + ' ' + shadowsRightClass);
3250
+ edge && !$videoPlaying && $el.addClass(edge.replace(/^|\s/g, ' ' + shadowsClass + '--'));
3251
+ }
3252
+ ////console.timeEnd('setShadow');
3253
+ }
3254
+
3255
+ that.destroy = function () {
3256
+ that.cancelFullScreen();
3257
+ that.stopAutoplay();
3258
+
3259
+ data = that.data = null;
3260
+
3261
+ appendElements();
3262
+
3263
+ activeIndexes = [];
3264
+ detachFrames(STAGE_FRAME_KEY);
3265
+
3266
+ reset.ok = false;
3267
+
3268
+ return this;
3269
+ };
3270
+
3271
+ that.playVideo = function () {
3272
+ var dataFrame = activeFrame,
3273
+ video = dataFrame.video,
3274
+ _activeIndex = activeIndex;
3275
+
3276
+ if (typeof video === 'object' && dataFrame.videoReady) {
3277
+ o_nativeFullScreen && that.fullScreen && that.cancelFullScreen();
3278
+
3279
+ waitFor(function () {
3280
+ return !fullScreenApi.is() || _activeIndex !== activeIndex;
3281
+ }, function () {
3282
+ if (_activeIndex === activeIndex) {
3283
+ dataFrame.$video = dataFrame.$video || $($.Fotorama.jst.video(video));
3284
+ dataFrame.$video.appendTo(dataFrame[STAGE_FRAME_KEY]);
3285
+
3286
+ $wrap.addClass(wrapVideoClass);
3287
+ $videoPlaying = dataFrame.$video;
3288
+
3289
+ stageNoMove();
3290
+
3291
+ $arrs.blur();
3292
+ $fullscreenIcon.blur();
3293
+
3294
+ triggerEvent('loadvideo');
3295
+ }
3296
+ });
3297
+ }
3298
+
3299
+ return this;
3300
+ };
3301
+
3302
+ that.stopVideo = function () {
3303
+ unloadVideo($videoPlaying, true, true);
3304
+ return this;
3305
+ };
3306
+
3307
+ function unloadVideo ($video, unloadActiveFLAG, releaseAutoplayFLAG) {
3308
+ if (unloadActiveFLAG) {
3309
+ $wrap.removeClass(wrapVideoClass);
3310
+ $videoPlaying = false;
3311
+
3312
+ stageNoMove();
3313
+ }
3314
+
3315
+ if ($video && $video !== $videoPlaying) {
3316
+ $video.remove();
3317
+ triggerEvent('unloadvideo');
3318
+ }
3319
+
3320
+ if (releaseAutoplayFLAG) {
3321
+ releaseAutoplay();
3322
+ changeAutoplay();
3323
+ }
3324
+ }
3325
+
3326
+ function toggleControlsClass (FLAG) {
3327
+ $wrap.toggleClass(wrapNoControlsClass, FLAG);
3328
+ }
3329
+
3330
+ function stageCursor (e) {
3331
+ if (stageShaftTouchTail.flow) return;
3332
+
3333
+ var x = e ? e.pageX : stageCursor.x,
3334
+ pointerFLAG = x && !disableDirrection(getDirection(x)) && opts.click;
3335
+
3336
+ if (stageCursor.p !== pointerFLAG
3337
+ && $stage.toggleClass(pointerClass, pointerFLAG)) {
3338
+ stageCursor.p = pointerFLAG;
3339
+ stageCursor.x = x;
3340
+ }
3341
+ }
3342
+
3343
+ $stage.on('mousemove', stageCursor);
3344
+
3345
+ function clickToShow (showOptions) {
3346
+ clearTimeout(clickToShow.t);
3347
+
3348
+ if (opts.clicktransition && opts.clicktransition !== opts.transition) {
3349
+ //console.log('change transition to: ' + opts.clicktransition);
3350
+
3351
+ // this timeout is for yield events flow
3352
+ setTimeout(function () {
3353
+ // save original transition for later
3354
+ var _o_transition = opts.transition;
3355
+
3356
+ that.setOptions({transition: opts.clicktransition});
3357
+
3358
+ // now safe to pass base transition to o_transition, so that.show will restor it
3359
+ o_transition = _o_transition;
3360
+ // this timeout is here to prevent jerking in some browsers
3361
+ clickToShow.t = setTimeout(function () {
3362
+ that.show(showOptions);
3363
+ }, 10);
3364
+ }, 0);
3365
+ } else {
3366
+ that.show(showOptions);
3367
+ }
3368
+ }
3369
+
3370
+ function onStageTap (e, toggleControlsFLAG) {
3371
+ ////console.time('onStageTap');
3372
+ var target = e.target,
3373
+ $target = $(target);
3374
+
3375
+ if ($target.hasClass(videoPlayClass)) {
3376
+ that.playVideo();
3377
+ } else if (target === fullscreenIcon) {
3378
+ that.toggleFullScreen();
3379
+ } else if ($videoPlaying) {
3380
+ target === videoClose && unloadVideo($videoPlaying, true, true);
3381
+ } else {
3382
+ if (toggleControlsFLAG) {
3383
+ toggleControlsClass();
3384
+ } else if (opts.click) {
3385
+
3386
+ clickToShow({index: e.shiftKey || getDirectionSign(getDirection(e._x)), slow: e.altKey, user: true});
3387
+ }
3388
+ }
3389
+ ////console.timeEnd('onStageTap');
3390
+ }
3391
+
3392
+ function updateTouchTails (key, value) {
3393
+ stageShaftTouchTail[key] = navShaftTouchTail[key] = value;
3394
+ }
3395
+
3396
+ stageShaftTouchTail = moveOnTouch($stageShaft, {
3397
+ onStart: onTouchStart,
3398
+ onMove: function (e, result) {
3399
+ setShadow($stage, result.edge);
3400
+ },
3401
+ onTouchEnd: onTouchEnd,
3402
+ onEnd: function (result) {
3403
+ ////console.time('stageShaftTouchTail.onEnd');
3404
+ setShadow($stage);
3405
+
3406
+ ////console.log('result', result);
3407
+
3408
+ var toggleControlsFLAG = (MS_POINTER && !hoverFLAG || result.touch) && opts.arrows && opts.arrows !== 'always';
3409
+
3410
+ if (result.moved || (toggleControlsFLAG && result.pos !== result.newPos && !result.control)) {
3411
+ var index = getIndexByPos(result.newPos, measures.w, opts.margin, repositionIndex);
3412
+ that.show({
3413
+ index: index,
3414
+ time: o_fade ? o_transitionDuration : result.time,
3415
+ overPos: result.overPos,
3416
+ user: true
3417
+ });
3418
+ } else if (!result.aborted && !result.control) {
3419
+ onStageTap(result.startEvent, toggleControlsFLAG);
3420
+ }
3421
+ ////console.timeEnd('stageShaftTouchTail.onEnd');
3422
+ },
3423
+ // getPos: function () {
3424
+ // return -getPosByIndex(dirtyIndex, measures.w, opts.margin, repositionIndex);
3425
+ // },
3426
+ //_001: true,
3427
+ timeLow: 1,
3428
+ timeHigh: 1,
3429
+ friction: 2,
3430
+ select: '.' + selectClass + ', .' + selectClass + ' *',
3431
+ $wrap: $stage
3432
+ });
3433
+
3434
+ navShaftTouchTail = moveOnTouch($navShaft, {
3435
+ onStart: onTouchStart,
3436
+ onMove: function (e, result) {
3437
+ setShadow($nav, result.edge);
3438
+ },
3439
+ onTouchEnd: onTouchEnd,
3440
+ onEnd: function (result) {
3441
+
3442
+ function onEnd () {
3443
+ slideNavShaft.l = result.newPos;
3444
+ releaseAutoplay();
3445
+ changeAutoplay();
3446
+ thumbsDraw(result.newPos, true);
3447
+ }
3448
+
3449
+ if (!result.moved) {
3450
+ var target = result.$target.closest('.' + navFrameClass, $navShaft)[0];
3451
+ target && onNavFrameClick.call(target, result.startEvent);
3452
+ } else if (result.pos !== result.newPos) {
3453
+ pausedAutoplayFLAG = true;
3454
+ slide($navShaft, {
3455
+ time: result.time,
3456
+ pos: result.newPos,
3457
+ overPos: result.overPos,
3458
+ onEnd: onEnd
3459
+ });
3460
+ thumbsDraw(result.newPos);
3461
+ o_shadows && setShadow($nav, findShadowEdge(result.newPos, navShaftTouchTail.min, navShaftTouchTail.max));
3462
+ } else {
3463
+ onEnd();
3464
+ }
3465
+ },
3466
+ timeLow: .5,
3467
+ timeHigh: 2,
3468
+ friction: 5,
3469
+ $wrap: $nav
3470
+ });
3471
+
3472
+ stageWheelTail = wheel($stage, {
3473
+ shift: true,
3474
+ onEnd: function (e, direction) {
3475
+ ////console.log('wheel $stage onEnd', direction);
3476
+ onTouchStart();
3477
+ onTouchEnd();
3478
+ that.show({index: direction, slow: e.altKey})
3479
+ }
3480
+ });
3481
+
3482
+ navWheelTail = wheel($nav, {
3483
+ onEnd: function (e, direction) {
3484
+ ////console.log('wheel $nav onEnd', direction);
3485
+ onTouchStart();
3486
+ onTouchEnd();
3487
+ var newPos = stop($navShaft) + direction * .25;
3488
+ $navShaft.css(getTranslate(minMaxLimit(newPos, navShaftTouchTail.min, navShaftTouchTail.max)));
3489
+ o_shadows && setShadow($nav, findShadowEdge(newPos, navShaftTouchTail.min, navShaftTouchTail.max));
3490
+ navWheelTail.prevent = {'<': newPos >= navShaftTouchTail.max, '>': newPos <= navShaftTouchTail.min};
3491
+ clearTimeout(navWheelTail.t);
3492
+ navWheelTail.t = setTimeout(function () {
3493
+ slideNavShaft.l = newPos;
3494
+ thumbsDraw(newPos, true)
3495
+ }, TOUCH_TIMEOUT);
3496
+ thumbsDraw(newPos);
3497
+ }
3498
+ });
3499
+
3500
+ $wrap.hover(
3501
+ function () {
3502
+ setTimeout(function () {
3503
+ if (touchedFLAG) return;
3504
+ toggleControlsClass(!(hoverFLAG = true));
3505
+ }, 0);
3506
+ }, function () {
3507
+ if (!hoverFLAG) return;
3508
+ toggleControlsClass(!(hoverFLAG = false));
3509
+ }
3510
+ );
3511
+
3512
+ function onNavFrameClick (e) {
3513
+ var index = $(this).data().eq;
3514
+ clickToShow({index: index, slow: e.altKey, user: true, coo: e._x - $nav.offset().left});
3515
+ }
3516
+
3517
+ function onArrClick (e) {
3518
+ clickToShow({index: $arrs.index(this) ? '>' : '<', slow: e.altKey, user: true});
3519
+ }
3520
+
3521
+ smartClick($arrs, function (e) {
3522
+ stopEvent(e);
3523
+ onArrClick.call(this, e);
3524
+ }, {
3525
+ onStart: function () {
3526
+ onTouchStart();
3527
+ stageShaftTouchTail.control = true;
3528
+ },
3529
+ onTouchEnd: onTouchEnd
3530
+ });
3531
+
3532
+ function addFocusOnControls (el) {
3533
+ addFocus(el, function () {
3534
+ setTimeout(function () {
3535
+ lockScroll($stage);
3536
+ }, 0);
3537
+ toggleControlsClass(false);
3538
+ });
3539
+ }
3540
+
3541
+ $arrs.each(function () {
3542
+ addEnterUp(this, function (e) {
3543
+ onArrClick.call(this, e);
3544
+ });
3545
+ addFocusOnControls(this);
3546
+ });
3547
+
3548
+ addEnterUp(fullscreenIcon, that.toggleFullScreen);
3549
+ addFocusOnControls(fullscreenIcon);
3550
+
3551
+ function reset () {
3552
+ setData();
3553
+ setOptions();
3554
+
3555
+ if (!reset.i) {
3556
+ reset.i = true;
3557
+ // Only once
3558
+ var _startindex = opts.startindex;
3559
+ if (_startindex || opts.hash && location.hash) {
3560
+ startIndex = getIndexFromHash(_startindex || location.hash.replace(/^#/, ''), data, that.index === 0 || _startindex, _startindex);
3561
+ }
3562
+ activeIndex = repositionIndex = dirtyIndex = lastActiveIndex = startIndex = edgeIndex(startIndex) || 0;/*(o_rtl ? size - 1 : 0)*///;
3563
+ }
3564
+
3565
+ if (size) {
3566
+ if (changeToRtl()) return;
3567
+
3568
+ if ($videoPlaying) {
3569
+ unloadVideo($videoPlaying, true);
3570
+ }
3571
+
3572
+ activeIndexes = [];
3573
+ detachFrames(STAGE_FRAME_KEY);
3574
+
3575
+ reset.ok = true;
3576
+
3577
+ that.show({index: activeIndex, time: 0});
3578
+ that.resize();
3579
+ } else {
3580
+ that.destroy();
3581
+ }
3582
+ }
3583
+
3584
+ function changeToRtl () {
3585
+ ////console.log('changeToRtl');
3586
+ if (!changeToRtl.f === o_rtl) {
3587
+ changeToRtl.f = o_rtl;
3588
+ activeIndex = size - 1 - activeIndex;
3589
+ ////console.log('changeToRtl execute, activeIndex is', activeIndex);
3590
+ that.reverse();
3591
+
3592
+ return true;
3593
+ }
3594
+ }
3595
+
3596
+ $.each('load push pop shift unshift reverse sort splice'.split(' '), function (i, method) {
3597
+ that[method] = function () {
3598
+ data = data || [];
3599
+ if (method !== 'load') {
3600
+ Array.prototype[method].apply(data, arguments);
3601
+ } else if (arguments[0] && typeof arguments[0] === 'object' && arguments[0].length) {
3602
+ data = clone(arguments[0]);
3603
+ }
3604
+ reset();
3605
+ return that;
3606
+ }
3607
+ });
3608
+
3609
+ function ready () {
3610
+ if (!ready.ok) {
3611
+ ready.ok = true;
3612
+ triggerEvent('ready');
3613
+ }
3614
+ }
3615
+
3616
+ reset();
3617
+ };
3618
+
3619
+
3620
+ $.fn.fotorama = function (opts) {
3621
+ return this.each(function () {
3622
+ var that = this,
3623
+ $fotorama = $(this),
3624
+ fotoramaData = $fotorama.data(),
3625
+ fotorama = fotoramaData.fotorama;
3626
+
3627
+ if (!fotorama) {
3628
+ waitFor(function () {
3629
+ return !isHidden(that);
3630
+ }, function () {
3631
+ fotoramaData.urtext = $fotorama.html();
3632
+ new $.Fotorama($fotorama,
3633
+ /* Priority for options:
3634
+ * 1. <div data-loop="true"></div>
3635
+ * 2. $('div').fotorama({loop: false})
3636
+ * 3. Defaults */
3637
+ $.extend(
3638
+ {},
3639
+ OPTIONS,
3640
+ window.fotoramaDefaults,
3641
+ opts,
3642
+ fotoramaData
3643
+ )
3644
+ );
3645
+ });
3646
+ } else {
3647
+ fotorama.setOptions(opts, true);
3648
+ }
3649
+ });
3650
+ };
3651
+ $.Fotorama.instances = [];
3652
+
3653
+ function calculateIndexes () {
3654
+ $.each($.Fotorama.instances, function (index, instance) {
3655
+ instance.index = index;
3656
+ });
3657
+ }
3658
+
3659
+ function addInstance (instance) {
3660
+ $.Fotorama.instances.push(instance);
3661
+ calculateIndexes();
3662
+ }
3663
+
3664
+ function hideInstance (instance) {
3665
+ $.Fotorama.instances.splice(instance.index, 1);
3666
+ calculateIndexes();
3667
+ }
3668
+ $.Fotorama.cache = {};
3669
+ $.Fotorama.measures = {};
3670
+ $ = $ || {};
3671
+ $.Fotorama = $.Fotorama || {};
3672
+ $.Fotorama.jst = $.Fotorama.jst || {};
3673
+
3674
+ $.Fotorama.jst.style = function(v) {
3675
+ var __t, __p = '', __e = _.escape;
3676
+ __p += '.fotorama' +
3677
+ ((__t = ( v.s )) == null ? '' : __t) +
3678
+ ' .fotorama__nav--thumbs .fotorama__nav__frame{\npadding:' +
3679
+ ((__t = ( v.m )) == null ? '' : __t) +
3680
+ 'px;\nheight:' +
3681
+ ((__t = ( v.h )) == null ? '' : __t) +
3682
+ 'px}\n.fotorama' +
3683
+ ((__t = ( v.s )) == null ? '' : __t) +
3684
+ ' .fotorama__thumb-border{\nheight:' +
3685
+ ((__t = ( v.h - v.b * (v.q ? 0 : 2) )) == null ? '' : __t) +
3686
+ 'px;\nborder-width:' +
3687
+ ((__t = ( v.b )) == null ? '' : __t) +
3688
+ 'px;\nmargin-top:' +
3689
+ ((__t = ( v.m )) == null ? '' : __t) +
3690
+ 'px}';
3691
+ return __p
3692
+ };
3693
+
3694
+ $.Fotorama.jst.video = function(v) {
3695
+ var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
3696
+ function print() { __p += __j.call(arguments, '') }
3697
+ __p += '<div class="fotorama__video"><iframe src="';
3698
+ 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 : '')) ;
3699
+ __p += '" frameborder="0" allowfullscreen></iframe></div>\n';
3700
+ return __p
3701
+ };
3702
+ $(function () {
3703
+ $('.' + _fotoramaClass + ':not([data-auto="false"])').fotorama();
3704
+ });
3705
+ })(window, document, location, typeof jQuery !== 'undefined' && jQuery);