fancybox3 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +37 -0
- data/app/assets/config/fancybox3_manifest.js +0 -0
- data/app/assets/javascripts/fancybox.js +4346 -0
- data/app/assets/javascripts/fancybox.min.js +12 -0
- data/app/assets/stylesheets/fancybox.css +616 -0
- data/app/assets/stylesheets/fancybox.min.css +1 -0
- data/lib/fancybox3.rb +5 -0
- data/lib/fancybox3/engine.rb +4 -0
- data/lib/fancybox3/version.rb +3 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: '092c17be4d4b2f7adb2303836e4a93ed2b5af47c'
|
4
|
+
data.tar.gz: 4e734181b5e4a2f14c845db84dba1d64a4e09e5c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 277754b60af3efa771904e0021b3c99a87833471a44b32ccae674dae40f58cb02fe9ffb6dcbbbacb9f2246861e49e2eda16e70c90df5c6c5d26ef484e6f2fc92
|
7
|
+
data.tar.gz: 0e1f15902fba081f8abc9686e7c47571a181ae819c4a59495abe38a73dfccb4037e1e989e57bcb34a4c39a4e6b28a832d1751a21502bfc4a57567c869596c35e
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Fancybox3
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'fancybox3'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install fancybox3
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Fancybox3'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
load 'rails/tasks/statistics.rake'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
require 'bundler/gem_tasks'
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
|
29
|
+
Rake::TestTask.new(:test) do |t|
|
30
|
+
t.libs << 'lib'
|
31
|
+
t.libs << 'test'
|
32
|
+
t.pattern = 'test/**/*_test.rb'
|
33
|
+
t.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
task default: :test
|
File without changes
|
@@ -0,0 +1,4346 @@
|
|
1
|
+
// ==================================================
|
2
|
+
// fancyBox v3.0.47
|
3
|
+
//
|
4
|
+
// Licensed GPLv3 for open source use
|
5
|
+
// or fancyBox Commercial License for commercial use
|
6
|
+
//
|
7
|
+
// http://fancyapps.com/fancybox/
|
8
|
+
// Copyright 2017 fancyApps
|
9
|
+
//
|
10
|
+
// ==================================================
|
11
|
+
;(function (window, document, $, undefined) {
|
12
|
+
'use strict';
|
13
|
+
|
14
|
+
// If there's no jQuery, fancyBox can't work
|
15
|
+
// =========================================
|
16
|
+
|
17
|
+
if ( !$ ) {
|
18
|
+
return undefined;
|
19
|
+
}
|
20
|
+
|
21
|
+
// Private default settings
|
22
|
+
// ========================
|
23
|
+
|
24
|
+
var defaults = {
|
25
|
+
|
26
|
+
// Animation duration in ms
|
27
|
+
speed : 330,
|
28
|
+
|
29
|
+
// Enable infinite gallery navigation
|
30
|
+
loop : true,
|
31
|
+
|
32
|
+
// Should zoom animation change opacity, too
|
33
|
+
// If opacity is 'auto', then fade-out if image and thumbnail have different aspect ratios
|
34
|
+
opacity : 'auto',
|
35
|
+
|
36
|
+
// Space around image, ignored if zoomed-in or viewport smaller than 800px
|
37
|
+
margin : [44, 0],
|
38
|
+
|
39
|
+
// Horizontal space between slides
|
40
|
+
gutter : 30,
|
41
|
+
|
42
|
+
// Should display toolbars
|
43
|
+
infobar : true,
|
44
|
+
buttons : true,
|
45
|
+
|
46
|
+
// What buttons should appear in the toolbar
|
47
|
+
slideShow : true,
|
48
|
+
fullScreen : true,
|
49
|
+
thumbs : true,
|
50
|
+
closeBtn : true,
|
51
|
+
|
52
|
+
// Should apply small close button at top right corner of the content
|
53
|
+
// If 'auto' - will be set for content having type 'html', 'inline' or 'ajax'
|
54
|
+
smallBtn : 'auto',
|
55
|
+
|
56
|
+
image : {
|
57
|
+
|
58
|
+
// Wait for images to load before displaying
|
59
|
+
// Requires predefined image dimensions
|
60
|
+
// If 'auto' - will zoom in thumbnail if 'width' and 'height' attributes are found
|
61
|
+
preload : "auto",
|
62
|
+
|
63
|
+
// Protect an image from downloading by right-click
|
64
|
+
protect : false
|
65
|
+
|
66
|
+
},
|
67
|
+
|
68
|
+
ajax : {
|
69
|
+
|
70
|
+
// Object containing settings for ajax request
|
71
|
+
settings : {
|
72
|
+
|
73
|
+
// This helps to indicate that request comes from the modal
|
74
|
+
// Feel free to change naming
|
75
|
+
data : {
|
76
|
+
fancybox : true
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
},
|
81
|
+
|
82
|
+
iframe : {
|
83
|
+
|
84
|
+
// Iframe template
|
85
|
+
tpl : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen allowtransparency="true" src=""></iframe>',
|
86
|
+
|
87
|
+
// Preload iframe before displaying it
|
88
|
+
// This allows to calculate iframe content width and height
|
89
|
+
// (note: Due to "Same Origin Policy", you can't get cross domain data).
|
90
|
+
preload : true,
|
91
|
+
|
92
|
+
// Scrolling attribute for iframe tag
|
93
|
+
scrolling : 'no',
|
94
|
+
|
95
|
+
// Custom CSS styling for iframe wrapping element
|
96
|
+
css : {}
|
97
|
+
|
98
|
+
},
|
99
|
+
|
100
|
+
// Custom CSS class for layout
|
101
|
+
baseClass : '',
|
102
|
+
|
103
|
+
// Custom CSS class for slide element
|
104
|
+
slideClass : '',
|
105
|
+
|
106
|
+
// Base template for layout
|
107
|
+
baseTpl : '<div class="fancybox-container" role="dialog" tabindex="-1">' +
|
108
|
+
'<div class="fancybox-bg"></div>' +
|
109
|
+
'<div class="fancybox-controls">' +
|
110
|
+
'<div class="fancybox-infobar">' +
|
111
|
+
'<button data-fancybox-previous class="fancybox-button fancybox-button--left" title="Previous"></button>' +
|
112
|
+
'<div class="fancybox-infobar__body">' +
|
113
|
+
'<span class="js-fancybox-index"></span> / <span class="js-fancybox-count"></span>' +
|
114
|
+
'</div>' +
|
115
|
+
'<button data-fancybox-next class="fancybox-button fancybox-button--right" title="Next"></button>' +
|
116
|
+
'</div>' +
|
117
|
+
'<div class="fancybox-buttons">' +
|
118
|
+
'<button data-fancybox-close class="fancybox-button fancybox-button--close" title="Close (Esc)"></button>' +
|
119
|
+
'</div>' +
|
120
|
+
'</div>' +
|
121
|
+
'<div class="fancybox-slider-wrap">' +
|
122
|
+
'<div class="fancybox-slider"></div>' +
|
123
|
+
'</div>' +
|
124
|
+
'<div class="fancybox-caption-wrap"><div class="fancybox-caption"></div></div>' +
|
125
|
+
'</div>',
|
126
|
+
|
127
|
+
// Loading indicator template
|
128
|
+
spinnerTpl : '<div class="fancybox-loading"></div>',
|
129
|
+
|
130
|
+
// Error message template
|
131
|
+
errorTpl : '<div class="fancybox-error"><p>The requested content cannot be loaded. <br /> Please try again later.<p></div>',
|
132
|
+
|
133
|
+
// This will be appended to html content, if "smallBtn" option is not set to false
|
134
|
+
closeTpl : '<button data-fancybox-close class="fancybox-close-small"></button>',
|
135
|
+
|
136
|
+
// Container is injected into this element
|
137
|
+
parentEl : 'body',
|
138
|
+
|
139
|
+
// Enable gestures (tap, zoom, pan and pinch)
|
140
|
+
touch : true,
|
141
|
+
|
142
|
+
// Enable keyboard navigation
|
143
|
+
keyboard : true,
|
144
|
+
|
145
|
+
// Try to focus on first focusable element after opening
|
146
|
+
focus : true,
|
147
|
+
|
148
|
+
// Close when clicked outside of the content
|
149
|
+
closeClickOutside : true,
|
150
|
+
|
151
|
+
// Callbacks
|
152
|
+
beforeLoad : $.noop,
|
153
|
+
afterLoad : $.noop,
|
154
|
+
beforeMove : $.noop,
|
155
|
+
afterMove : $.noop,
|
156
|
+
onComplete : $.noop,
|
157
|
+
|
158
|
+
onInit : $.noop,
|
159
|
+
beforeClose : $.noop,
|
160
|
+
afterClose : $.noop,
|
161
|
+
onActivate : $.noop,
|
162
|
+
onDeactivate : $.noop
|
163
|
+
|
164
|
+
};
|
165
|
+
|
166
|
+
var $W = $(window);
|
167
|
+
var $D = $(document);
|
168
|
+
|
169
|
+
var called = 0;
|
170
|
+
|
171
|
+
// Check if an object is a jQuery object and not a native JavaScript object
|
172
|
+
// ========================================================================
|
173
|
+
|
174
|
+
var isQuery = function (obj) {
|
175
|
+
return obj && obj.hasOwnProperty && obj instanceof $;
|
176
|
+
};
|
177
|
+
|
178
|
+
// Handle multiple browsers for requestAnimationFrame()
|
179
|
+
// ====================================================
|
180
|
+
|
181
|
+
var requestAFrame = (function() {
|
182
|
+
return window.requestAnimationFrame ||
|
183
|
+
window.webkitRequestAnimationFrame ||
|
184
|
+
window.mozRequestAnimationFrame ||
|
185
|
+
function( callback ) {
|
186
|
+
window.setTimeout(callback, 1000 / 60); };
|
187
|
+
})();
|
188
|
+
|
189
|
+
|
190
|
+
// Check if element is inside the viewport by at least 1 pixel
|
191
|
+
// ===========================================================
|
192
|
+
|
193
|
+
var isElementInViewport = function( el ) {
|
194
|
+
var rect;
|
195
|
+
|
196
|
+
if ( typeof $ === "function" && el instanceof $ ) {
|
197
|
+
el = el[0];
|
198
|
+
}
|
199
|
+
|
200
|
+
rect = el.getBoundingClientRect();
|
201
|
+
|
202
|
+
return rect.bottom > 0 && rect.right > 0 &&
|
203
|
+
rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
|
204
|
+
rect.top < (window.innerHeight || document.documentElement.clientHeight);
|
205
|
+
};
|
206
|
+
|
207
|
+
|
208
|
+
// Class definition
|
209
|
+
// ================
|
210
|
+
|
211
|
+
var FancyBox = function( content, opts, index ) {
|
212
|
+
var self = this;
|
213
|
+
|
214
|
+
self.opts = $.extend( true, { index : index }, defaults, opts || {} );
|
215
|
+
self.id = self.opts.id || ++called;
|
216
|
+
self.group = [];
|
217
|
+
|
218
|
+
self.currIndex = parseInt( self.opts.index, 10 ) || 0;
|
219
|
+
self.prevIndex = null;
|
220
|
+
|
221
|
+
self.prevPos = null;
|
222
|
+
self.currPos = 0;
|
223
|
+
|
224
|
+
self.firstRun = null;
|
225
|
+
|
226
|
+
// Create group elements from original item collection
|
227
|
+
self.createGroup( content );
|
228
|
+
|
229
|
+
if ( !self.group.length ) {
|
230
|
+
return;
|
231
|
+
}
|
232
|
+
|
233
|
+
// Save last active element and current scroll position
|
234
|
+
self.$lastFocus = $(document.activeElement).blur();
|
235
|
+
|
236
|
+
// Collection of gallery objects
|
237
|
+
self.slides = {};
|
238
|
+
|
239
|
+
self.init( content );
|
240
|
+
|
241
|
+
};
|
242
|
+
|
243
|
+
$.extend(FancyBox.prototype, {
|
244
|
+
|
245
|
+
// Create DOM structure
|
246
|
+
// ====================
|
247
|
+
|
248
|
+
init : function() {
|
249
|
+
var self = this;
|
250
|
+
|
251
|
+
var galleryHasHtml = false;
|
252
|
+
|
253
|
+
var testWidth;
|
254
|
+
var $container;
|
255
|
+
|
256
|
+
self.scrollTop = $D.scrollTop();
|
257
|
+
self.scrollLeft = $D.scrollLeft();
|
258
|
+
|
259
|
+
if ( !$.fancybox.getInstance() ) {
|
260
|
+
testWidth = $( 'body' ).width();
|
261
|
+
|
262
|
+
$( 'html' ).addClass( 'fancybox-enabled' );
|
263
|
+
|
264
|
+
if ( $.fancybox.isTouch ) {
|
265
|
+
|
266
|
+
// Ugly workaround for iOS page shifting issue (when inputs get focus)
|
267
|
+
// Do not apply for images, otherwise top/bottom bars will appear
|
268
|
+
$.each( self.group, function( key, item ) {
|
269
|
+
if ( item.type !== 'image' && item.type !== 'iframe' ) {
|
270
|
+
galleryHasHtml = true;
|
271
|
+
return false;
|
272
|
+
}
|
273
|
+
});
|
274
|
+
|
275
|
+
if ( galleryHasHtml ) {
|
276
|
+
$('body').css({
|
277
|
+
position : 'fixed',
|
278
|
+
width : testWidth,
|
279
|
+
top : self.scrollTop * -1
|
280
|
+
});
|
281
|
+
}
|
282
|
+
|
283
|
+
} else {
|
284
|
+
|
285
|
+
// Compare page width after adding "overflow:hidden"
|
286
|
+
testWidth = $( 'body' ).width() - testWidth;
|
287
|
+
|
288
|
+
// Width has changed - compensate missing scrollbars
|
289
|
+
if ( testWidth > 1 ) {
|
290
|
+
$( '<style id="fancybox-noscroll" type="text/css">' ).html( '.compensate-for-scrollbar, .fancybox-enabled body { margin-right: ' + testWidth + 'px; }' ).appendTo( 'head' );
|
291
|
+
}
|
292
|
+
|
293
|
+
}
|
294
|
+
}
|
295
|
+
|
296
|
+
$container = $( self.opts.baseTpl )
|
297
|
+
.attr('id', 'fancybox-container-' + self.id)
|
298
|
+
.data( 'FancyBox', self )
|
299
|
+
.addClass( self.opts.baseClass )
|
300
|
+
.hide()
|
301
|
+
.prependTo( self.opts.parentEl );
|
302
|
+
|
303
|
+
// Create object holding references to jQuery wrapped nodes
|
304
|
+
self.$refs = {
|
305
|
+
container : $container,
|
306
|
+
bg : $container.find('.fancybox-bg'),
|
307
|
+
controls : $container.find('.fancybox-controls'),
|
308
|
+
buttons : $container.find('.fancybox-buttons'),
|
309
|
+
slider_wrap : $container.find('.fancybox-slider-wrap'),
|
310
|
+
slider : $container.find('.fancybox-slider'),
|
311
|
+
caption : $container.find('.fancybox-caption')
|
312
|
+
};
|
313
|
+
|
314
|
+
self.trigger( 'onInit' );
|
315
|
+
|
316
|
+
// Bring to front and enable events
|
317
|
+
self.activate();
|
318
|
+
|
319
|
+
// Try to avoid running multiple times
|
320
|
+
if ( self.current ) {
|
321
|
+
return;
|
322
|
+
}
|
323
|
+
|
324
|
+
self.jumpTo( self.currIndex );
|
325
|
+
|
326
|
+
},
|
327
|
+
|
328
|
+
|
329
|
+
// Create array of gally item objects
|
330
|
+
// Check if each object has valid type and content
|
331
|
+
// ===============================================
|
332
|
+
|
333
|
+
createGroup : function ( content ) {
|
334
|
+
var self = this;
|
335
|
+
var items = $.makeArray( content );
|
336
|
+
|
337
|
+
$.each(items, function( i, item ) {
|
338
|
+
var obj = {},
|
339
|
+
opts = {},
|
340
|
+
data = [],
|
341
|
+
$item,
|
342
|
+
type,
|
343
|
+
src,
|
344
|
+
srcParts;
|
345
|
+
|
346
|
+
// Step 1 - Make sure we have an object
|
347
|
+
|
348
|
+
if ( $.isPlainObject( item ) ) {
|
349
|
+
|
350
|
+
obj = item;
|
351
|
+
opts = item.opts || {};
|
352
|
+
|
353
|
+
} else if ( $.type( item ) === 'object' && $( item ).length ) {
|
354
|
+
|
355
|
+
$item = $( item );
|
356
|
+
data = $item.data();
|
357
|
+
|
358
|
+
opts = 'options' in data ? data.options : {};
|
359
|
+
|
360
|
+
opts = $.type( opts ) === 'object' ? opts : {};
|
361
|
+
|
362
|
+
obj.type = 'type' in data ? data.type : opts.type;
|
363
|
+
obj.src = 'src' in data ? data.src : ( opts.src || $item.attr( 'href' ) );
|
364
|
+
|
365
|
+
opts.width = 'width' in data ? data.width : opts.width;
|
366
|
+
opts.height = 'height' in data ? data.height : opts.height;
|
367
|
+
opts.thumb = 'thumb' in data ? data.thumb : opts.thumb;
|
368
|
+
|
369
|
+
opts.selector = 'selector' in data ? data.selector : opts.selector;
|
370
|
+
|
371
|
+
if ( 'srcset' in data ) {
|
372
|
+
opts.image = { srcset : data.srcset };
|
373
|
+
}
|
374
|
+
|
375
|
+
opts.$orig = $item;
|
376
|
+
|
377
|
+
} else {
|
378
|
+
|
379
|
+
obj = {
|
380
|
+
type : 'html',
|
381
|
+
content : item + ''
|
382
|
+
};
|
383
|
+
|
384
|
+
}
|
385
|
+
|
386
|
+
obj.opts = $.extend( true, {}, self.opts, opts );
|
387
|
+
|
388
|
+
// Step 2 - Make sure we have supported content type
|
389
|
+
|
390
|
+
type = obj.type;
|
391
|
+
src = obj.src || '';
|
392
|
+
|
393
|
+
if ( !type ) {
|
394
|
+
|
395
|
+
if ( obj.content ) {
|
396
|
+
type = 'html';
|
397
|
+
|
398
|
+
} else if ( src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i) ) {
|
399
|
+
type = 'image';
|
400
|
+
|
401
|
+
} else if ( src.match(/\.(pdf)((\?|#).*)?$/i) ) {
|
402
|
+
type = 'pdf';
|
403
|
+
|
404
|
+
} else if ( src.charAt(0) === '#' ) {
|
405
|
+
type = 'inline';
|
406
|
+
|
407
|
+
}
|
408
|
+
|
409
|
+
obj.type = type;
|
410
|
+
|
411
|
+
}
|
412
|
+
|
413
|
+
// Step 3 - Some adjustments
|
414
|
+
|
415
|
+
obj.index = self.group.length;
|
416
|
+
|
417
|
+
// Check if $orig and $thumb objects exist
|
418
|
+
if ( obj.opts.$orig && !obj.opts.$orig.length ) {
|
419
|
+
delete obj.opts.$orig;
|
420
|
+
}
|
421
|
+
|
422
|
+
if ( !obj.opts.$thumb && obj.opts.$orig ) {
|
423
|
+
obj.opts.$thumb = obj.opts.$orig.find( 'img:first' );
|
424
|
+
}
|
425
|
+
|
426
|
+
if ( obj.opts.$thumb && !obj.opts.$thumb.length ) {
|
427
|
+
delete obj.opts.$thumb;
|
428
|
+
}
|
429
|
+
|
430
|
+
// Caption is a "special" option, it can be passed as a method
|
431
|
+
if ( $.type( obj.opts.caption ) === 'function' ) {
|
432
|
+
obj.opts.caption = obj.opts.caption.apply( item, [ self, obj ] );
|
433
|
+
|
434
|
+
} else if ( 'caption' in data ) {
|
435
|
+
obj.opts.caption = data.caption;
|
436
|
+
|
437
|
+
} else if ( opts.$orig ) {
|
438
|
+
obj.opts.caption = $item.attr( 'title' );
|
439
|
+
}
|
440
|
+
|
441
|
+
// Make sure we have caption as a string
|
442
|
+
obj.opts.caption = obj.opts.caption === undefined ? '' : obj.opts.caption + '';
|
443
|
+
|
444
|
+
// Check if url contains selector used to filter the content
|
445
|
+
// Example: "ajax.html #something"
|
446
|
+
if ( type === 'ajax' ) {
|
447
|
+
srcParts = src.split(/\s+/, 2);
|
448
|
+
|
449
|
+
if ( srcParts.length > 1 ) {
|
450
|
+
obj.src = srcParts.shift();
|
451
|
+
|
452
|
+
obj.opts.selector = srcParts.shift();
|
453
|
+
}
|
454
|
+
}
|
455
|
+
|
456
|
+
if ( obj.opts.smallBtn == 'auto' ) {
|
457
|
+
|
458
|
+
if ( $.inArray( type, ['html', 'inline', 'ajax'] ) > -1 ) {
|
459
|
+
obj.opts.buttons = false;
|
460
|
+
obj.opts.smallBtn = true;
|
461
|
+
|
462
|
+
} else {
|
463
|
+
obj.opts.smallBtn = false;
|
464
|
+
}
|
465
|
+
|
466
|
+
}
|
467
|
+
|
468
|
+
if ( type === 'pdf' ) {
|
469
|
+
|
470
|
+
obj.type = 'iframe';
|
471
|
+
|
472
|
+
obj.opts.closeBtn = true;
|
473
|
+
obj.opts.smallBtn = false;
|
474
|
+
|
475
|
+
obj.opts.iframe.preload = false;
|
476
|
+
|
477
|
+
}
|
478
|
+
|
479
|
+
if ( obj.opts.modal ) {
|
480
|
+
|
481
|
+
$.extend(true, obj.opts, {
|
482
|
+
infobar : 0,
|
483
|
+
buttons : 0,
|
484
|
+
keyboard : 0,
|
485
|
+
slideShow : 0,
|
486
|
+
fullScreen : 0,
|
487
|
+
closeClickOutside : 0
|
488
|
+
});
|
489
|
+
|
490
|
+
}
|
491
|
+
|
492
|
+
self.group.push( obj );
|
493
|
+
|
494
|
+
});
|
495
|
+
|
496
|
+
},
|
497
|
+
|
498
|
+
|
499
|
+
// Attach an event handler functions for:
|
500
|
+
// - navigation elements
|
501
|
+
// - browser scrolling, resizing;
|
502
|
+
// - focusing
|
503
|
+
// - keyboard
|
504
|
+
// =================
|
505
|
+
|
506
|
+
addEvents : function() {
|
507
|
+
var self = this;
|
508
|
+
|
509
|
+
self.removeEvents();
|
510
|
+
|
511
|
+
// Make navigation elements clickable
|
512
|
+
|
513
|
+
self.$refs.container.on('click.fb-close', '[data-fancybox-close]', function(e) {
|
514
|
+
e.stopPropagation();
|
515
|
+
e.preventDefault();
|
516
|
+
|
517
|
+
self.close( e );
|
518
|
+
|
519
|
+
}).on('click.fb-previous', '[data-fancybox-previous]', function(e) {
|
520
|
+
e.stopPropagation();
|
521
|
+
e.preventDefault();
|
522
|
+
|
523
|
+
self.previous();
|
524
|
+
|
525
|
+
}).on('click.fb-next', '[data-fancybox-next]', function(e) {
|
526
|
+
e.stopPropagation();
|
527
|
+
e.preventDefault();
|
528
|
+
|
529
|
+
self.next();
|
530
|
+
});
|
531
|
+
|
532
|
+
|
533
|
+
// Handle page scrolling and browser resizing
|
534
|
+
|
535
|
+
$( window ).on('orientationchange.fb resize.fb', function(e) {
|
536
|
+
requestAFrame(function() {
|
537
|
+
|
538
|
+
if ( e && e.originalEvent && e.originalEvent.type === "resize" ) {
|
539
|
+
self.update();
|
540
|
+
|
541
|
+
} else {
|
542
|
+
self.$refs.slider_wrap.hide();
|
543
|
+
|
544
|
+
requestAFrame(function () {
|
545
|
+
self.$refs.slider_wrap.show();
|
546
|
+
|
547
|
+
self.update();
|
548
|
+
});
|
549
|
+
|
550
|
+
}
|
551
|
+
|
552
|
+
});
|
553
|
+
});
|
554
|
+
|
555
|
+
|
556
|
+
// Trap focus
|
557
|
+
|
558
|
+
$D.on('focusin.fb', function(e) {
|
559
|
+
var instance = $.fancybox ? $.fancybox.getInstance() : null;
|
560
|
+
|
561
|
+
if ( instance && !$( e.target ).hasClass( 'fancybox-container' ) && !$.contains( instance.$refs.container[0], e.target ) ) {
|
562
|
+
e.stopPropagation();
|
563
|
+
|
564
|
+
instance.focus();
|
565
|
+
|
566
|
+
// Sometimes page gets scrolled, set it back
|
567
|
+
$W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
|
568
|
+
}
|
569
|
+
|
570
|
+
});
|
571
|
+
|
572
|
+
// Enable keyboard navigation
|
573
|
+
|
574
|
+
$D.on('keydown.fb', function (e) {
|
575
|
+
var current = self.current,
|
576
|
+
keycode = e.keyCode || e.which;
|
577
|
+
|
578
|
+
if ( !current || !current.opts.keyboard ) {
|
579
|
+
return;
|
580
|
+
}
|
581
|
+
|
582
|
+
if ( $(e.target).is('input') || $(e.target).is('textarea') ) {
|
583
|
+
return;
|
584
|
+
}
|
585
|
+
|
586
|
+
// Backspace and Esc keys
|
587
|
+
if ( keycode === 8 || keycode === 27 ) {
|
588
|
+
e.preventDefault();
|
589
|
+
|
590
|
+
self.close( e );
|
591
|
+
|
592
|
+
return;
|
593
|
+
}
|
594
|
+
|
595
|
+
switch ( keycode ) {
|
596
|
+
|
597
|
+
case 37: // Left arrow
|
598
|
+
case 38: // Up arrow
|
599
|
+
|
600
|
+
e.preventDefault();
|
601
|
+
|
602
|
+
self.previous();
|
603
|
+
|
604
|
+
break;
|
605
|
+
|
606
|
+
case 39: // Right arrow
|
607
|
+
case 40: // Down arrow
|
608
|
+
|
609
|
+
e.preventDefault();
|
610
|
+
|
611
|
+
self.next();
|
612
|
+
|
613
|
+
break;
|
614
|
+
|
615
|
+
case 80: // "P"
|
616
|
+
case 32: // Spacebar
|
617
|
+
|
618
|
+
e.preventDefault();
|
619
|
+
|
620
|
+
if ( self.SlideShow ) {
|
621
|
+
e.preventDefault();
|
622
|
+
|
623
|
+
self.SlideShow.toggle();
|
624
|
+
}
|
625
|
+
|
626
|
+
break;
|
627
|
+
|
628
|
+
case 70: // "F"
|
629
|
+
|
630
|
+
if ( self.FullScreen ) {
|
631
|
+
e.preventDefault();
|
632
|
+
|
633
|
+
self.FullScreen.toggle();
|
634
|
+
}
|
635
|
+
|
636
|
+
break;
|
637
|
+
|
638
|
+
case 71: // "G"
|
639
|
+
|
640
|
+
if ( self.Thumbs ) {
|
641
|
+
e.preventDefault();
|
642
|
+
|
643
|
+
self.Thumbs.toggle();
|
644
|
+
}
|
645
|
+
|
646
|
+
break;
|
647
|
+
}
|
648
|
+
});
|
649
|
+
|
650
|
+
|
651
|
+
},
|
652
|
+
|
653
|
+
|
654
|
+
// Remove events added by the core
|
655
|
+
// ===============================
|
656
|
+
|
657
|
+
removeEvents : function () {
|
658
|
+
|
659
|
+
$W.off( 'scroll.fb resize.fb orientationchange.fb' );
|
660
|
+
$D.off( 'keydown.fb focusin.fb click.fb-close' );
|
661
|
+
|
662
|
+
this.$refs.container.off('click.fb-close click.fb-previous click.fb-next');
|
663
|
+
},
|
664
|
+
|
665
|
+
|
666
|
+
// Slide to left
|
667
|
+
// ==================
|
668
|
+
|
669
|
+
previous : function( duration ) {
|
670
|
+
this.jumpTo( this.currIndex - 1, duration );
|
671
|
+
},
|
672
|
+
|
673
|
+
|
674
|
+
// Slide to right
|
675
|
+
// ===================
|
676
|
+
|
677
|
+
next : function( duration ) {
|
678
|
+
this.jumpTo( this.currIndex + 1, duration );
|
679
|
+
},
|
680
|
+
|
681
|
+
|
682
|
+
// Display current gallery item, move slider to current position
|
683
|
+
// =============================================================
|
684
|
+
|
685
|
+
jumpTo : function ( to, duration ) {
|
686
|
+
var self = this,
|
687
|
+
firstRun,
|
688
|
+
index,
|
689
|
+
pos,
|
690
|
+
loop;
|
691
|
+
|
692
|
+
firstRun = self.firstRun = ( self.firstRun === null );
|
693
|
+
|
694
|
+
index = pos = to = parseInt( to, 10 );
|
695
|
+
loop = self.current ? self.current.opts.loop : false;
|
696
|
+
|
697
|
+
if ( self.isAnimating || ( index == self.currIndex && !firstRun ) ) {
|
698
|
+
return;
|
699
|
+
}
|
700
|
+
|
701
|
+
if ( self.group.length > 1 && loop ) {
|
702
|
+
|
703
|
+
index = index % self.group.length;
|
704
|
+
index = index < 0 ? self.group.length + index : index;
|
705
|
+
|
706
|
+
// Calculate closest position of upcoming item from the current one
|
707
|
+
if ( self.group.length == 2 ) {
|
708
|
+
pos = to - self.currIndex + self.currPos;
|
709
|
+
|
710
|
+
} else {
|
711
|
+
pos = index - self.currIndex + self.currPos;
|
712
|
+
|
713
|
+
if ( Math.abs( self.currPos - ( pos + self.group.length ) ) < Math.abs( self.currPos - pos ) ) {
|
714
|
+
pos = pos + self.group.length;
|
715
|
+
|
716
|
+
} else if ( Math.abs( self.currPos - ( pos - self.group.length ) ) < Math.abs( self.currPos - pos ) ) {
|
717
|
+
pos = pos - self.group.length;
|
718
|
+
|
719
|
+
}
|
720
|
+
}
|
721
|
+
|
722
|
+
} else if ( !self.group[ index ] ) {
|
723
|
+
self.update( false, false, duration );
|
724
|
+
|
725
|
+
return;
|
726
|
+
}
|
727
|
+
|
728
|
+
if ( self.current ) {
|
729
|
+
self.current.$slide.removeClass('fancybox-slide--current fancybox-slide--complete');
|
730
|
+
|
731
|
+
self.updateSlide( self.current, true );
|
732
|
+
}
|
733
|
+
|
734
|
+
self.prevIndex = self.currIndex;
|
735
|
+
self.prevPos = self.currPos;
|
736
|
+
|
737
|
+
self.currIndex = index;
|
738
|
+
self.currPos = pos;
|
739
|
+
|
740
|
+
// Create slides
|
741
|
+
|
742
|
+
self.current = self.createSlide( pos );
|
743
|
+
|
744
|
+
if ( self.group.length > 1 ) {
|
745
|
+
|
746
|
+
if ( self.opts.loop || pos - 1 >= 0 ) {
|
747
|
+
self.createSlide( pos - 1 );
|
748
|
+
}
|
749
|
+
|
750
|
+
if ( self.opts.loop || pos + 1 < self.group.length ) {
|
751
|
+
self.createSlide( pos + 1 );
|
752
|
+
}
|
753
|
+
}
|
754
|
+
|
755
|
+
self.current.isMoved = false;
|
756
|
+
self.current.isComplete = false;
|
757
|
+
|
758
|
+
duration = parseInt( duration === undefined ? self.current.opts.speed * 1.5 : duration, 10 );
|
759
|
+
|
760
|
+
// Move slider to the next position
|
761
|
+
// Note: the content might still be loading
|
762
|
+
self.trigger( 'beforeMove' );
|
763
|
+
|
764
|
+
self.updateControls();
|
765
|
+
|
766
|
+
if ( firstRun ) {
|
767
|
+
self.current.$slide.addClass('fancybox-slide--current');
|
768
|
+
|
769
|
+
self.$refs.container.show();
|
770
|
+
|
771
|
+
requestAFrame(function() {
|
772
|
+
self.$refs.bg.css('transition-duration', self.current.opts.speed + 'ms');
|
773
|
+
|
774
|
+
self.$refs.container.addClass( 'fancybox-container--ready' );
|
775
|
+
});
|
776
|
+
}
|
777
|
+
|
778
|
+
// Set position immediately on first opening
|
779
|
+
self.update( true, false, firstRun ? 0 : duration, function() {
|
780
|
+
self.afterMove();
|
781
|
+
});
|
782
|
+
|
783
|
+
self.loadSlide( self.current );
|
784
|
+
|
785
|
+
if ( !( firstRun && self.current.$ghost ) ) {
|
786
|
+
self.preload();
|
787
|
+
}
|
788
|
+
|
789
|
+
},
|
790
|
+
|
791
|
+
|
792
|
+
// Create new "slide" element
|
793
|
+
// These are gallery items that are actually added to DOM
|
794
|
+
// =======================================================
|
795
|
+
|
796
|
+
createSlide : function( pos ) {
|
797
|
+
|
798
|
+
var self = this;
|
799
|
+
var $slide;
|
800
|
+
var index;
|
801
|
+
var found;
|
802
|
+
|
803
|
+
index = pos % self.group.length;
|
804
|
+
index = index < 0 ? self.group.length + index : index;
|
805
|
+
|
806
|
+
if ( !self.slides[ pos ] && self.group[ index ] ) {
|
807
|
+
|
808
|
+
// If we are looping and slide with that index already exists, then reuse it
|
809
|
+
if ( self.opts.loop && self.group.length > 2 ) {
|
810
|
+
for (var key in self.slides) {
|
811
|
+
if ( self.slides[ key ].index === index ) {
|
812
|
+
found = self.slides[ key ];
|
813
|
+
found.pos = pos;
|
814
|
+
|
815
|
+
self.slides[ pos ] = found;
|
816
|
+
|
817
|
+
delete self.slides[ key ];
|
818
|
+
|
819
|
+
self.updateSlide( found );
|
820
|
+
|
821
|
+
return found;
|
822
|
+
}
|
823
|
+
}
|
824
|
+
}
|
825
|
+
|
826
|
+
$slide = $('<div class="fancybox-slide"></div>').appendTo( self.$refs.slider );
|
827
|
+
|
828
|
+
self.slides[ pos ] = $.extend( true, {}, self.group[ index ], {
|
829
|
+
pos : pos,
|
830
|
+
$slide : $slide,
|
831
|
+
isMoved : false,
|
832
|
+
isLoaded : false
|
833
|
+
});
|
834
|
+
|
835
|
+
}
|
836
|
+
|
837
|
+
return self.slides[ pos ];
|
838
|
+
|
839
|
+
},
|
840
|
+
|
841
|
+
zoomInOut : function( type, duration, callback ) {
|
842
|
+
|
843
|
+
var self = this;
|
844
|
+
var current = self.current;
|
845
|
+
var $what = current.$placeholder;
|
846
|
+
var opacity = current.opts.opacity;
|
847
|
+
var $thumb = current.opts.$thumb;
|
848
|
+
var thumbPos = $thumb ? $thumb.offset() : 0;
|
849
|
+
var slidePos = current.$slide.offset();
|
850
|
+
var props;
|
851
|
+
var start;
|
852
|
+
var end;
|
853
|
+
|
854
|
+
if ( !$what || !current.isMoved || !thumbPos || !isElementInViewport( $thumb ) ) {
|
855
|
+
return false;
|
856
|
+
}
|
857
|
+
|
858
|
+
if ( type === 'In' && !self.firstRun ) {
|
859
|
+
return false;
|
860
|
+
}
|
861
|
+
|
862
|
+
$.fancybox.stop( $what );
|
863
|
+
|
864
|
+
self.isAnimating = true;
|
865
|
+
|
866
|
+
props = {
|
867
|
+
top : thumbPos.top - slidePos.top + parseFloat( $thumb.css( "border-top-width" ) || 0 ),
|
868
|
+
left : thumbPos.left - slidePos.left + parseFloat( $thumb.css( "border-left-width" ) || 0 ),
|
869
|
+
width : $thumb.width(),
|
870
|
+
height : $thumb.height(),
|
871
|
+
scaleX : 1,
|
872
|
+
scaleY : 1
|
873
|
+
};
|
874
|
+
|
875
|
+
// Check if we need to animate opacity
|
876
|
+
if ( opacity == 'auto' ) {
|
877
|
+
opacity = Math.abs( current.width / current.height - props.width / props.height ) > 0.1;
|
878
|
+
}
|
879
|
+
|
880
|
+
if ( type === 'In' ) {
|
881
|
+
start = props;
|
882
|
+
end = self.getFitPos( current );
|
883
|
+
|
884
|
+
end.scaleX = end.width / start.width;
|
885
|
+
end.scaleY = end.height / start.height;
|
886
|
+
|
887
|
+
if ( opacity ) {
|
888
|
+
start.opacity = 0.1;
|
889
|
+
end.opacity = 1;
|
890
|
+
}
|
891
|
+
|
892
|
+
} else {
|
893
|
+
|
894
|
+
start = $.fancybox.getTranslate( $what );
|
895
|
+
end = props;
|
896
|
+
|
897
|
+
// Switch to thumbnail image to improve animation performance
|
898
|
+
if ( current.$ghost ) {
|
899
|
+
current.$ghost.show();
|
900
|
+
|
901
|
+
if ( current.$image ) {
|
902
|
+
current.$image.remove();
|
903
|
+
}
|
904
|
+
}
|
905
|
+
|
906
|
+
start.scaleX = start.width / end.width;
|
907
|
+
start.scaleY = start.height / end.height;
|
908
|
+
|
909
|
+
start.width = end.width;
|
910
|
+
start.height = end.height;
|
911
|
+
|
912
|
+
if ( opacity ) {
|
913
|
+
end.opacity = 0;
|
914
|
+
}
|
915
|
+
|
916
|
+
}
|
917
|
+
|
918
|
+
self.updateCursor( end.width, end.height );
|
919
|
+
|
920
|
+
// There is no need to animate width/height properties
|
921
|
+
delete end.width;
|
922
|
+
delete end.height;
|
923
|
+
|
924
|
+
$.fancybox.setTranslate( $what, start );
|
925
|
+
|
926
|
+
$what.show();
|
927
|
+
|
928
|
+
self.trigger( 'beforeZoom' + type );
|
929
|
+
|
930
|
+
$what.css( 'transition', 'all ' + duration + 'ms' );
|
931
|
+
|
932
|
+
$.fancybox.setTranslate( $what, end );
|
933
|
+
|
934
|
+
setTimeout(function() {
|
935
|
+
var reset;
|
936
|
+
|
937
|
+
$what.css( 'transition', 'none' );
|
938
|
+
|
939
|
+
reset = $.fancybox.getTranslate( $what );
|
940
|
+
|
941
|
+
reset.scaleX = 1;
|
942
|
+
reset.scaleY = 1;
|
943
|
+
|
944
|
+
// Reset scalex/scaleY values; this helps for perfomance
|
945
|
+
$.fancybox.setTranslate( $what, reset );
|
946
|
+
|
947
|
+
self.trigger( 'afterZoom' + type );
|
948
|
+
|
949
|
+
callback.apply( self );
|
950
|
+
|
951
|
+
self.isAnimating = false;
|
952
|
+
|
953
|
+
}, duration);
|
954
|
+
|
955
|
+
|
956
|
+
return true;
|
957
|
+
|
958
|
+
},
|
959
|
+
|
960
|
+
// Check if image dimensions exceed parent element
|
961
|
+
// ===============================================
|
962
|
+
|
963
|
+
canPan : function() {
|
964
|
+
|
965
|
+
var self = this;
|
966
|
+
|
967
|
+
var current = self.current;
|
968
|
+
var $what = current.$placeholder;
|
969
|
+
|
970
|
+
var rez = false;
|
971
|
+
|
972
|
+
if ( $what ) {
|
973
|
+
rez = self.getFitPos( current );
|
974
|
+
rez = Math.abs( $what.width() - rez.width ) > 1 || Math.abs( $what.height() - rez.height ) > 1;
|
975
|
+
|
976
|
+
}
|
977
|
+
|
978
|
+
return rez;
|
979
|
+
|
980
|
+
},
|
981
|
+
|
982
|
+
|
983
|
+
// Check if current image dimensions are smaller than actual
|
984
|
+
// =========================================================
|
985
|
+
|
986
|
+
isScaledDown : function() {
|
987
|
+
|
988
|
+
var self = this;
|
989
|
+
|
990
|
+
var current = self.current;
|
991
|
+
var $what = current.$placeholder;
|
992
|
+
|
993
|
+
var rez = false;
|
994
|
+
|
995
|
+
if ( $what ) {
|
996
|
+
rez = $.fancybox.getTranslate( $what );
|
997
|
+
rez = rez.width < current.width || rez.height < current.height;
|
998
|
+
}
|
999
|
+
|
1000
|
+
return rez;
|
1001
|
+
|
1002
|
+
},
|
1003
|
+
|
1004
|
+
|
1005
|
+
// Scale image to the actual size of the image
|
1006
|
+
// ===========================================
|
1007
|
+
|
1008
|
+
scaleToActual : function( x, y, duration ) {
|
1009
|
+
|
1010
|
+
var self = this;
|
1011
|
+
|
1012
|
+
var current = self.current;
|
1013
|
+
var $what = current.$placeholder;
|
1014
|
+
|
1015
|
+
var imgPos, posX, posY, scaleX, scaleY;
|
1016
|
+
|
1017
|
+
var canvasWidth = parseInt( current.$slide.width(), 10 );
|
1018
|
+
var canvasHeight = parseInt( current.$slide.height(), 10 );
|
1019
|
+
|
1020
|
+
var newImgWidth = current.width;
|
1021
|
+
var newImgHeight = current.height;
|
1022
|
+
|
1023
|
+
if ( !$what ) {
|
1024
|
+
return;
|
1025
|
+
}
|
1026
|
+
|
1027
|
+
self.isAnimating = true;
|
1028
|
+
|
1029
|
+
x = x === undefined ? canvasWidth * 0.5 : x;
|
1030
|
+
y = y === undefined ? canvasHeight * 0.5 : y;
|
1031
|
+
|
1032
|
+
imgPos = $.fancybox.getTranslate( $what );
|
1033
|
+
|
1034
|
+
scaleX = newImgWidth / imgPos.width;
|
1035
|
+
scaleY = newImgHeight / imgPos.height;
|
1036
|
+
|
1037
|
+
// Get center position for original image
|
1038
|
+
posX = ( canvasWidth * 0.5 - newImgWidth * 0.5 );
|
1039
|
+
posY = ( canvasHeight * 0.5 - newImgHeight * 0.5 );
|
1040
|
+
|
1041
|
+
// Make sure image does not move away from edges
|
1042
|
+
|
1043
|
+
if ( newImgWidth > canvasWidth ) {
|
1044
|
+
posX = imgPos.left * scaleX - ( ( x * scaleX ) - x );
|
1045
|
+
|
1046
|
+
if ( posX > 0 ) {
|
1047
|
+
posX = 0;
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
if ( posX < canvasWidth - newImgWidth ) {
|
1051
|
+
posX = canvasWidth - newImgWidth;
|
1052
|
+
}
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
if ( newImgHeight > canvasHeight) {
|
1056
|
+
posY = imgPos.top * scaleY - ( ( y * scaleY ) - y );
|
1057
|
+
|
1058
|
+
if ( posY > 0 ) {
|
1059
|
+
posY = 0;
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
if ( posY < canvasHeight - newImgHeight ) {
|
1063
|
+
posY = canvasHeight - newImgHeight;
|
1064
|
+
}
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
self.updateCursor( newImgWidth, newImgHeight );
|
1068
|
+
|
1069
|
+
$.fancybox.animate( $what, null, {
|
1070
|
+
top : posY,
|
1071
|
+
left : posX,
|
1072
|
+
scaleX : scaleX,
|
1073
|
+
scaleY : scaleY
|
1074
|
+
}, duration || current.opts.speed, function() {
|
1075
|
+
self.isAnimating = false;
|
1076
|
+
});
|
1077
|
+
|
1078
|
+
},
|
1079
|
+
|
1080
|
+
|
1081
|
+
// Scale image to fit inside parent element
|
1082
|
+
// ========================================
|
1083
|
+
|
1084
|
+
scaleToFit : function( duration ) {
|
1085
|
+
|
1086
|
+
var self = this;
|
1087
|
+
|
1088
|
+
var current = self.current;
|
1089
|
+
var $what = current.$placeholder;
|
1090
|
+
var end;
|
1091
|
+
|
1092
|
+
if ( !$what ) {
|
1093
|
+
return;
|
1094
|
+
}
|
1095
|
+
|
1096
|
+
self.isAnimating = true;
|
1097
|
+
|
1098
|
+
end = self.getFitPos( current );
|
1099
|
+
|
1100
|
+
self.updateCursor( end.width, end.height );
|
1101
|
+
|
1102
|
+
$.fancybox.animate( $what, null, {
|
1103
|
+
top : end.top,
|
1104
|
+
left : end.left,
|
1105
|
+
scaleX : end.width / $what.width(),
|
1106
|
+
scaleY : end.height / $what.height()
|
1107
|
+
}, duration || current.opts.speed, function() {
|
1108
|
+
self.isAnimating = false;
|
1109
|
+
});
|
1110
|
+
|
1111
|
+
},
|
1112
|
+
|
1113
|
+
// Calculate image size to fit inside viewport
|
1114
|
+
// ===========================================
|
1115
|
+
|
1116
|
+
getFitPos : function( slide ) {
|
1117
|
+
var $what = slide.$placeholder || slide.$content;
|
1118
|
+
|
1119
|
+
var imgWidth = slide.width;
|
1120
|
+
var imgHeight = slide.height;
|
1121
|
+
|
1122
|
+
var margin = slide.opts.margin;
|
1123
|
+
|
1124
|
+
var canvasWidth, canvasHeight, minRatio, top, left, width, height;
|
1125
|
+
|
1126
|
+
if ( !$what || !$what.length || ( !imgWidth && !imgHeight) ) {
|
1127
|
+
return false;
|
1128
|
+
}
|
1129
|
+
|
1130
|
+
// Convert "margin to CSS style: [ top, right, bottom, left ]
|
1131
|
+
if ( $.type( margin ) === "number" ) {
|
1132
|
+
margin = [ margin, margin ];
|
1133
|
+
}
|
1134
|
+
|
1135
|
+
if ( margin.length == 2 ) {
|
1136
|
+
margin = [ margin[0], margin[1], margin[0], margin[1] ];
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
if ( $W.width() < 800 ) {
|
1140
|
+
margin = [0, 0, 0, 0];
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
canvasWidth = parseInt( slide.$slide.width(), 10 ) - ( margin[ 1 ] + margin[ 3 ] );
|
1144
|
+
canvasHeight = parseInt( slide.$slide.height(), 10 ) - ( margin[ 0 ] + margin[ 2 ] );
|
1145
|
+
|
1146
|
+
minRatio = Math.min(1, canvasWidth / imgWidth, canvasHeight / imgHeight );
|
1147
|
+
|
1148
|
+
// Use floor rounding to make sure it really fits
|
1149
|
+
|
1150
|
+
width = Math.floor( minRatio * imgWidth );
|
1151
|
+
height = Math.floor( minRatio * imgHeight );
|
1152
|
+
|
1153
|
+
top = Math.floor( ( canvasHeight - height ) * 0.5 ) + margin[ 0 ];
|
1154
|
+
left = Math.floor( ( canvasWidth - width ) * 0.5 ) + margin[ 3 ];
|
1155
|
+
|
1156
|
+
return {
|
1157
|
+
top : top,
|
1158
|
+
left : left,
|
1159
|
+
width : width,
|
1160
|
+
height : height
|
1161
|
+
};
|
1162
|
+
|
1163
|
+
},
|
1164
|
+
|
1165
|
+
// Move slider to current position
|
1166
|
+
// Update all slides (and their content)
|
1167
|
+
// =====================================
|
1168
|
+
|
1169
|
+
update : function( andSlides, andContent, duration, callback ) {
|
1170
|
+
|
1171
|
+
var self = this;
|
1172
|
+
var leftValue;
|
1173
|
+
|
1174
|
+
if ( self.isAnimating === true || !self.current ) {
|
1175
|
+
return;
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
leftValue = ( self.current.pos * Math.floor( self.current.$slide.width() ) * -1 ) - ( self.current.pos * self.current.opts.gutter );
|
1179
|
+
duration = parseInt( duration, 10 ) || 0;
|
1180
|
+
|
1181
|
+
$.fancybox.stop( self.$refs.slider );
|
1182
|
+
|
1183
|
+
if ( andSlides === false ) {
|
1184
|
+
self.updateSlide( self.current, andContent );
|
1185
|
+
|
1186
|
+
} else {
|
1187
|
+
|
1188
|
+
$.each( self.slides, function( key, slide ) {
|
1189
|
+
self.updateSlide( slide, andContent );
|
1190
|
+
});
|
1191
|
+
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
if ( duration ) {
|
1195
|
+
|
1196
|
+
$.fancybox.animate( self.$refs.slider, null, {
|
1197
|
+
top : 0,
|
1198
|
+
left : leftValue
|
1199
|
+
}, duration, function() {
|
1200
|
+
self.current.isMoved = true;
|
1201
|
+
|
1202
|
+
if ( $.type( callback ) === 'function' ) {
|
1203
|
+
callback.apply( self );
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
});
|
1207
|
+
|
1208
|
+
} else {
|
1209
|
+
|
1210
|
+
$.fancybox.setTranslate( self.$refs.slider, { top : 0, left : leftValue } );
|
1211
|
+
|
1212
|
+
self.current.isMoved = true;
|
1213
|
+
|
1214
|
+
if ( $.type( callback ) === 'function' ) {
|
1215
|
+
callback.apply( self );
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
},
|
1221
|
+
|
1222
|
+
|
1223
|
+
// Update slide position and scale content to fit
|
1224
|
+
// ==============================================
|
1225
|
+
|
1226
|
+
updateSlide : function( slide, andContent ) {
|
1227
|
+
|
1228
|
+
var self = this;
|
1229
|
+
var $what = slide.$placeholder;
|
1230
|
+
var leftPos;
|
1231
|
+
|
1232
|
+
slide = slide || self.current;
|
1233
|
+
|
1234
|
+
if ( !slide || self.isClosing ) {
|
1235
|
+
return;
|
1236
|
+
}
|
1237
|
+
|
1238
|
+
leftPos = ( slide.pos * Math.floor( slide.$slide.width() ) ) + ( slide.pos * slide.opts.gutter);
|
1239
|
+
|
1240
|
+
if ( leftPos !== slide.leftPos ) {
|
1241
|
+
$.fancybox.setTranslate( slide.$slide, { top: 0, left : leftPos } );
|
1242
|
+
|
1243
|
+
slide.leftPos = leftPos;
|
1244
|
+
}
|
1245
|
+
|
1246
|
+
if ( andContent !== false && $what ) {
|
1247
|
+
$.fancybox.setTranslate( $what, self.getFitPos( slide ) );
|
1248
|
+
|
1249
|
+
if ( slide.pos === self.currPos ) {
|
1250
|
+
self.updateCursor();
|
1251
|
+
}
|
1252
|
+
}
|
1253
|
+
|
1254
|
+
slide.$slide.trigger( 'refresh' );
|
1255
|
+
|
1256
|
+
self.trigger( 'onUpdate', slide );
|
1257
|
+
},
|
1258
|
+
|
1259
|
+
// Update cursor style depending if content can be zoomed
|
1260
|
+
// ======================================================
|
1261
|
+
|
1262
|
+
updateCursor : function( nextWidth, nextHeight ) {
|
1263
|
+
|
1264
|
+
var self = this;
|
1265
|
+
var canScale;
|
1266
|
+
|
1267
|
+
var $container = self.$refs.container.removeClass('fancybox-controls--canzoomIn fancybox-controls--canzoomOut fancybox-controls--canGrab');
|
1268
|
+
|
1269
|
+
if ( self.isClosing || !self.opts.touch ) {
|
1270
|
+
return;
|
1271
|
+
}
|
1272
|
+
|
1273
|
+
if ( nextWidth !== undefined && nextHeight !== undefined ) {
|
1274
|
+
canScale = nextWidth < self.current.width && nextHeight < self.current.height;
|
1275
|
+
|
1276
|
+
} else {
|
1277
|
+
canScale = self.isScaledDown();
|
1278
|
+
}
|
1279
|
+
|
1280
|
+
if ( canScale ) {
|
1281
|
+
$container.addClass('fancybox-controls--canzoomIn');
|
1282
|
+
|
1283
|
+
} else if ( self.group.length < 2 ) {
|
1284
|
+
$container.addClass('fancybox-controls--canzoomOut');
|
1285
|
+
|
1286
|
+
} else {
|
1287
|
+
$container.addClass('fancybox-controls--canGrab');
|
1288
|
+
}
|
1289
|
+
|
1290
|
+
},
|
1291
|
+
|
1292
|
+
// Load content into the slide
|
1293
|
+
// ===========================
|
1294
|
+
|
1295
|
+
loadSlide : function( slide ) {
|
1296
|
+
|
1297
|
+
var self = this, type, $slide;
|
1298
|
+
var ajaxLoad;
|
1299
|
+
|
1300
|
+
if ( !slide || slide.isLoaded || slide.isLoading ) {
|
1301
|
+
return;
|
1302
|
+
}
|
1303
|
+
|
1304
|
+
slide.isLoading = true;
|
1305
|
+
|
1306
|
+
self.trigger( 'beforeLoad', slide );
|
1307
|
+
|
1308
|
+
type = slide.type;
|
1309
|
+
$slide = slide.$slide;
|
1310
|
+
|
1311
|
+
$slide
|
1312
|
+
.off( 'refresh' )
|
1313
|
+
.trigger( 'onReset' )
|
1314
|
+
.addClass( 'fancybox-slide--' + ( type || 'unknown' ) )
|
1315
|
+
.addClass( slide.opts.slideClass );
|
1316
|
+
|
1317
|
+
// Create content depending on the type
|
1318
|
+
|
1319
|
+
switch ( type ) {
|
1320
|
+
|
1321
|
+
case 'image':
|
1322
|
+
|
1323
|
+
self.setImage( slide );
|
1324
|
+
|
1325
|
+
break;
|
1326
|
+
|
1327
|
+
case 'iframe':
|
1328
|
+
|
1329
|
+
self.setIframe( slide );
|
1330
|
+
|
1331
|
+
break;
|
1332
|
+
|
1333
|
+
case 'html':
|
1334
|
+
|
1335
|
+
self.setContent( slide, slide.content );
|
1336
|
+
|
1337
|
+
break;
|
1338
|
+
|
1339
|
+
case 'inline':
|
1340
|
+
|
1341
|
+
if ( $( slide.src ).length ) {
|
1342
|
+
self.setContent( slide, $( slide.src ) );
|
1343
|
+
|
1344
|
+
} else {
|
1345
|
+
self.setError( slide );
|
1346
|
+
}
|
1347
|
+
|
1348
|
+
break;
|
1349
|
+
|
1350
|
+
case 'ajax':
|
1351
|
+
|
1352
|
+
self.showLoading( slide );
|
1353
|
+
|
1354
|
+
ajaxLoad = $.ajax( $.extend( {}, slide.opts.ajax.settings, {
|
1355
|
+
|
1356
|
+
url: slide.src,
|
1357
|
+
|
1358
|
+
success: function ( data, textStatus ) {
|
1359
|
+
|
1360
|
+
if ( textStatus === 'success' ) {
|
1361
|
+
self.setContent( slide, data );
|
1362
|
+
}
|
1363
|
+
|
1364
|
+
},
|
1365
|
+
|
1366
|
+
error: function ( jqXHR, textStatus ) {
|
1367
|
+
|
1368
|
+
if ( jqXHR && textStatus !== 'abort' ) {
|
1369
|
+
self.setError( slide );
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
}
|
1373
|
+
|
1374
|
+
}));
|
1375
|
+
|
1376
|
+
$slide.one( 'onReset', function () {
|
1377
|
+
ajaxLoad.abort();
|
1378
|
+
});
|
1379
|
+
|
1380
|
+
break;
|
1381
|
+
|
1382
|
+
default:
|
1383
|
+
|
1384
|
+
self.setError( slide );
|
1385
|
+
|
1386
|
+
break;
|
1387
|
+
|
1388
|
+
}
|
1389
|
+
|
1390
|
+
return true;
|
1391
|
+
|
1392
|
+
},
|
1393
|
+
|
1394
|
+
|
1395
|
+
// Use thumbnail image, if possible
|
1396
|
+
// ================================
|
1397
|
+
|
1398
|
+
setImage : function( slide ) {
|
1399
|
+
|
1400
|
+
var self = this;
|
1401
|
+
var srcset = slide.opts.image.srcset;
|
1402
|
+
|
1403
|
+
var found, temp, pxRatio, windowWidth;
|
1404
|
+
|
1405
|
+
if ( slide.isLoaded && !slide.hasError ) {
|
1406
|
+
self.afterLoad( slide );
|
1407
|
+
|
1408
|
+
return;
|
1409
|
+
}
|
1410
|
+
|
1411
|
+
// If we have "srcset", then we need to find matching "src" value.
|
1412
|
+
// This is necessary, because when you set an src attribute, the browser will preload the image
|
1413
|
+
// before any javascript or even CSS is applied.
|
1414
|
+
if ( srcset ) {
|
1415
|
+
pxRatio = window.devicePixelRatio || 1;
|
1416
|
+
windowWidth = window.innerWidth * pxRatio;
|
1417
|
+
|
1418
|
+
temp = srcset.split(',').map(function (el) {
|
1419
|
+
var ret = {};
|
1420
|
+
|
1421
|
+
el.trim().split(/\s+/).forEach(function (el, i) {
|
1422
|
+
var value = parseInt(el.substring(0, el.length - 1), 10);
|
1423
|
+
|
1424
|
+
if ( i === 0 ) {
|
1425
|
+
return (ret.url = el);
|
1426
|
+
}
|
1427
|
+
|
1428
|
+
if ( value ) {
|
1429
|
+
ret.value = value;
|
1430
|
+
ret.postfix = el[el.length - 1];
|
1431
|
+
}
|
1432
|
+
|
1433
|
+
});
|
1434
|
+
|
1435
|
+
return ret;
|
1436
|
+
});
|
1437
|
+
|
1438
|
+
// Sort by value
|
1439
|
+
temp.sort(function (a, b) {
|
1440
|
+
return a.value - b.value;
|
1441
|
+
});
|
1442
|
+
|
1443
|
+
// Ok, now we have an array of all srcset values
|
1444
|
+
for ( var j = 0; j < temp.length; j++ ) {
|
1445
|
+
var el = temp[ j ];
|
1446
|
+
|
1447
|
+
if ( ( el.postfix === 'w' && el.value >= windowWidth ) || ( el.postfix === 'x' && el.value >= pxRatio ) ) {
|
1448
|
+
found = el;
|
1449
|
+
break;
|
1450
|
+
}
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
// If not found, take the last one
|
1454
|
+
if ( !found && temp.length ) {
|
1455
|
+
found = temp[ temp.length - 1 ];
|
1456
|
+
}
|
1457
|
+
|
1458
|
+
if ( found ) {
|
1459
|
+
slide.src = found.url;
|
1460
|
+
|
1461
|
+
// If we have default width/height values, we can calculate height for matching source
|
1462
|
+
if ( slide.width && slide.height && found.postfix == 'w' ) {
|
1463
|
+
slide.height = ( slide.width / slide.height ) * found.value;
|
1464
|
+
slide.width = found.value;
|
1465
|
+
}
|
1466
|
+
}
|
1467
|
+
}
|
1468
|
+
|
1469
|
+
slide.$placeholder = $('<div class="fancybox-placeholder"></div>')
|
1470
|
+
.hide()
|
1471
|
+
.appendTo( slide.$slide );
|
1472
|
+
|
1473
|
+
if ( slide.opts.preload !== false && slide.opts.width && slide.opts.height && ( slide.opts.thumb || slide.opts.$thumb ) ) {
|
1474
|
+
|
1475
|
+
slide.width = slide.opts.width;
|
1476
|
+
slide.height = slide.opts.height;
|
1477
|
+
|
1478
|
+
slide.$ghost = $('<img />')
|
1479
|
+
.one('load error', function() {
|
1480
|
+
|
1481
|
+
if ( self.isClosing ) {
|
1482
|
+
return;
|
1483
|
+
}
|
1484
|
+
|
1485
|
+
// Start preloading full size image
|
1486
|
+
$('<img/>')[0].src = slide.src;
|
1487
|
+
|
1488
|
+
// zoomIn or just show
|
1489
|
+
self.revealImage( slide, function() {
|
1490
|
+
|
1491
|
+
self.setBigImage( slide );
|
1492
|
+
|
1493
|
+
if ( self.firstRun && slide.index === self.currIndex ) {
|
1494
|
+
self.preload();
|
1495
|
+
}
|
1496
|
+
});
|
1497
|
+
|
1498
|
+
})
|
1499
|
+
.addClass( 'fancybox-image' )
|
1500
|
+
.appendTo( slide.$placeholder )
|
1501
|
+
.attr( 'src', slide.opts.thumb || slide.opts.$thumb.attr( 'src' ) );
|
1502
|
+
|
1503
|
+
} else {
|
1504
|
+
|
1505
|
+
self.setBigImage( slide );
|
1506
|
+
|
1507
|
+
}
|
1508
|
+
|
1509
|
+
},
|
1510
|
+
|
1511
|
+
|
1512
|
+
// Create full-size image
|
1513
|
+
// ======================
|
1514
|
+
|
1515
|
+
setBigImage : function ( slide ) {
|
1516
|
+
var self = this;
|
1517
|
+
var $img = $('<img />');
|
1518
|
+
|
1519
|
+
slide.$image = $img
|
1520
|
+
.one('error', function() {
|
1521
|
+
|
1522
|
+
self.setError( slide );
|
1523
|
+
|
1524
|
+
})
|
1525
|
+
.one('load', function() {
|
1526
|
+
|
1527
|
+
// Clear timeout that checks if loading icon needs to be displayed
|
1528
|
+
clearTimeout( slide.timouts );
|
1529
|
+
|
1530
|
+
slide.timouts = null;
|
1531
|
+
|
1532
|
+
if ( self.isClosing ) {
|
1533
|
+
return;
|
1534
|
+
}
|
1535
|
+
|
1536
|
+
slide.width = this.naturalWidth;
|
1537
|
+
slide.height = this.naturalHeight;
|
1538
|
+
|
1539
|
+
if ( slide.opts.image.srcset ) {
|
1540
|
+
$img.attr('sizes', '100vw').attr('srcset', slide.opts.image.srcset);
|
1541
|
+
}
|
1542
|
+
|
1543
|
+
self.afterLoad( slide );
|
1544
|
+
|
1545
|
+
if ( slide.$ghost ) {
|
1546
|
+
slide.timouts = setTimeout(function() {
|
1547
|
+
slide.$ghost.hide();
|
1548
|
+
|
1549
|
+
}, 350);
|
1550
|
+
}
|
1551
|
+
|
1552
|
+
})
|
1553
|
+
.addClass('fancybox-image')
|
1554
|
+
.attr('src', slide.src)
|
1555
|
+
.appendTo( slide.$placeholder );
|
1556
|
+
|
1557
|
+
if ( $img[0].complete ) {
|
1558
|
+
$img.trigger('load');
|
1559
|
+
|
1560
|
+
} else if( $img[0].error ) {
|
1561
|
+
$img.trigger('error');
|
1562
|
+
|
1563
|
+
} else {
|
1564
|
+
|
1565
|
+
slide.timouts = setTimeout(function() {
|
1566
|
+
if ( !$img[0].complete && !slide.hasError ) {
|
1567
|
+
self.showLoading( slide );
|
1568
|
+
}
|
1569
|
+
|
1570
|
+
}, 150);
|
1571
|
+
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
if ( slide.opts.image.protect ) {
|
1575
|
+
$('<div class="fancybox-spaceball"></div>').appendTo( slide.$placeholder ).on('contextmenu.fb',function(e){
|
1576
|
+
if ( e.button == 2 ) {
|
1577
|
+
e.preventDefault();
|
1578
|
+
}
|
1579
|
+
|
1580
|
+
return true;
|
1581
|
+
});
|
1582
|
+
}
|
1583
|
+
|
1584
|
+
},
|
1585
|
+
|
1586
|
+
// Simply show image holder without animation
|
1587
|
+
// It has been hidden initially to avoid flickering
|
1588
|
+
// ================================================
|
1589
|
+
|
1590
|
+
revealImage : function( slide, callback ) {
|
1591
|
+
|
1592
|
+
var self = this;
|
1593
|
+
|
1594
|
+
callback = callback || $.noop;
|
1595
|
+
|
1596
|
+
if ( slide.type !== 'image' || slide.hasError || slide.isRevealed === true ) {
|
1597
|
+
|
1598
|
+
callback.apply( self );
|
1599
|
+
|
1600
|
+
return;
|
1601
|
+
}
|
1602
|
+
|
1603
|
+
slide.isRevealed = true;
|
1604
|
+
|
1605
|
+
if ( !( slide.pos === self.currPos && self.zoomInOut( 'In', slide.opts.speed, callback ) ) ) {
|
1606
|
+
|
1607
|
+
if ( slide.$ghost && !slide.isLoaded ) {
|
1608
|
+
self.updateSlide( slide, true );
|
1609
|
+
}
|
1610
|
+
|
1611
|
+
if ( slide.pos === self.currPos ) {
|
1612
|
+
$.fancybox.animate( slide.$placeholder, { opacity: 0 }, { opacity: 1 }, 300, callback );
|
1613
|
+
|
1614
|
+
} else {
|
1615
|
+
slide.$placeholder.show();
|
1616
|
+
}
|
1617
|
+
|
1618
|
+
callback.apply( self );
|
1619
|
+
|
1620
|
+
}
|
1621
|
+
|
1622
|
+
},
|
1623
|
+
|
1624
|
+
// Create iframe wrapper, iframe and bindings
|
1625
|
+
// ==========================================
|
1626
|
+
|
1627
|
+
setIframe : function( slide ) {
|
1628
|
+
var self = this,
|
1629
|
+
opts = slide.opts.iframe,
|
1630
|
+
$slide = slide.$slide,
|
1631
|
+
$iframe;
|
1632
|
+
|
1633
|
+
slide.$content = $('<div class="fancybox-content"></div>')
|
1634
|
+
.css( opts.css )
|
1635
|
+
.appendTo( $slide );
|
1636
|
+
|
1637
|
+
$iframe = $( opts.tpl.replace(/\{rnd\}/g, new Date().getTime()) )
|
1638
|
+
.attr('scrolling', $.fancybox.isTouch ? 'auto' : opts.scrolling)
|
1639
|
+
.appendTo( slide.$content );
|
1640
|
+
|
1641
|
+
if ( opts.preload ) {
|
1642
|
+
slide.$content.addClass( 'fancybox-tmp' );
|
1643
|
+
|
1644
|
+
self.showLoading( slide );
|
1645
|
+
|
1646
|
+
// Unfortunately, it is not always possible to determine if iframe is successfully loaded
|
1647
|
+
// (due to browser security policy)
|
1648
|
+
|
1649
|
+
$iframe.on('load.fb error.fb', function(e) {
|
1650
|
+
this.isReady = 1;
|
1651
|
+
|
1652
|
+
slide.$slide.trigger( 'refresh' );
|
1653
|
+
|
1654
|
+
self.afterLoad( slide );
|
1655
|
+
|
1656
|
+
});
|
1657
|
+
|
1658
|
+
// Recalculate iframe content size
|
1659
|
+
|
1660
|
+
$slide.on('refresh.fb', function() {
|
1661
|
+
var $wrap = slide.$content,
|
1662
|
+
$contents,
|
1663
|
+
$body,
|
1664
|
+
scrollWidth,
|
1665
|
+
frameWidth,
|
1666
|
+
frameHeight;
|
1667
|
+
|
1668
|
+
if ( $iframe[0].isReady !== 1 ) {
|
1669
|
+
return;
|
1670
|
+
}
|
1671
|
+
|
1672
|
+
// Check if content is accessible,
|
1673
|
+
// it will fail if frame is not with the same origin
|
1674
|
+
|
1675
|
+
try {
|
1676
|
+
$contents = $iframe.contents();
|
1677
|
+
$body = $contents.find('body');
|
1678
|
+
|
1679
|
+
} catch (ignore) {}
|
1680
|
+
|
1681
|
+
// Calculate dimensions for the wrapper
|
1682
|
+
|
1683
|
+
if ( $body && $body.length && !( opts.css.width !== undefined && opts.css.height !== undefined ) ) {
|
1684
|
+
|
1685
|
+
scrollWidth = $iframe[0].contentWindow.document.documentElement.scrollWidth;
|
1686
|
+
|
1687
|
+
frameWidth = Math.ceil( $body.outerWidth(true) + ( $wrap.width() - scrollWidth ) );
|
1688
|
+
frameHeight = Math.ceil( $body.outerHeight(true) );
|
1689
|
+
|
1690
|
+
// Resize wrapper to fit iframe content
|
1691
|
+
|
1692
|
+
$wrap.css({
|
1693
|
+
'width' : opts.css.width === undefined ? frameWidth + ( $wrap.outerWidth() - $wrap.innerWidth() ) : opts.css.width,
|
1694
|
+
'height' : opts.css.height === undefined ? frameHeight + ( $wrap.outerHeight() - $wrap.innerHeight() ) : opts.css.height
|
1695
|
+
});
|
1696
|
+
|
1697
|
+
}
|
1698
|
+
|
1699
|
+
$wrap.removeClass( 'fancybox-tmp' );
|
1700
|
+
|
1701
|
+
});
|
1702
|
+
|
1703
|
+
} else {
|
1704
|
+
|
1705
|
+
this.afterLoad( slide );
|
1706
|
+
|
1707
|
+
}
|
1708
|
+
|
1709
|
+
$iframe.attr( 'src', slide.src );
|
1710
|
+
|
1711
|
+
if ( slide.opts.smallBtn ) {
|
1712
|
+
slide.$content.prepend( slide.opts.closeTpl );
|
1713
|
+
}
|
1714
|
+
|
1715
|
+
// Remove iframe if closing or changing gallery item
|
1716
|
+
|
1717
|
+
$slide.one('onReset', function () {
|
1718
|
+
|
1719
|
+
// This helps IE not to throw errors when closing
|
1720
|
+
|
1721
|
+
try {
|
1722
|
+
|
1723
|
+
$(this).find('iframe').hide().attr('src', '//about:blank');
|
1724
|
+
|
1725
|
+
} catch (ignore) {}
|
1726
|
+
|
1727
|
+
$(this).empty();
|
1728
|
+
|
1729
|
+
slide.isLoaded = false;
|
1730
|
+
|
1731
|
+
});
|
1732
|
+
|
1733
|
+
},
|
1734
|
+
|
1735
|
+
|
1736
|
+
// Wrap and append content to the slide
|
1737
|
+
// ======================================
|
1738
|
+
|
1739
|
+
setContent : function ( slide, content ) {
|
1740
|
+
|
1741
|
+
var self = this;
|
1742
|
+
|
1743
|
+
if ( self.isClosing ) {
|
1744
|
+
return;
|
1745
|
+
}
|
1746
|
+
|
1747
|
+
self.hideLoading( slide );
|
1748
|
+
|
1749
|
+
slide.$slide.empty();
|
1750
|
+
|
1751
|
+
if ( isQuery( content ) && content.parent().length ) {
|
1752
|
+
|
1753
|
+
// If it is a jQuery object, then it will be moved to the box.
|
1754
|
+
// The placeholder is created so we will know where to put it back.
|
1755
|
+
// If user is navigating gallery fast, then the content might be already moved to the box
|
1756
|
+
|
1757
|
+
if ( content.data( 'placeholder' ) ) {
|
1758
|
+
content.parents('.fancybox-slide').trigger( 'onReset' );
|
1759
|
+
}
|
1760
|
+
|
1761
|
+
content.data({'placeholder' : $('<div></div>' ).hide().insertAfter( content ) }).css('display', 'inline-block');
|
1762
|
+
|
1763
|
+
} else {
|
1764
|
+
|
1765
|
+
if ( $.type( content ) === 'string' ) {
|
1766
|
+
|
1767
|
+
content = $('<div>').append( content ).contents();
|
1768
|
+
|
1769
|
+
if ( content[0].nodeType === 3 ) {
|
1770
|
+
content = $('<div>').html( content );
|
1771
|
+
}
|
1772
|
+
|
1773
|
+
}
|
1774
|
+
|
1775
|
+
if ( slide.opts.selector ) {
|
1776
|
+
content = $('<div>').html( content ).find( slide.opts.selector );
|
1777
|
+
}
|
1778
|
+
|
1779
|
+
}
|
1780
|
+
|
1781
|
+
slide.$slide.one('onReset', function () {
|
1782
|
+
var placeholder = isQuery( content ) ? content.data('placeholder') : 0;
|
1783
|
+
|
1784
|
+
if ( placeholder ) {
|
1785
|
+
content.hide().replaceAll( placeholder );
|
1786
|
+
|
1787
|
+
content.data( 'placeholder', null );
|
1788
|
+
}
|
1789
|
+
|
1790
|
+
if ( !slide.hasError ) {
|
1791
|
+
$(this).empty();
|
1792
|
+
|
1793
|
+
slide.isLoaded = false;
|
1794
|
+
}
|
1795
|
+
|
1796
|
+
});
|
1797
|
+
|
1798
|
+
slide.$content = $( content ).appendTo( slide.$slide );
|
1799
|
+
|
1800
|
+
if ( slide.opts.smallBtn === true ) {
|
1801
|
+
slide.$content.find( '.fancybox-close-small' ).remove().end().eq(0).append( slide.opts.closeTpl );
|
1802
|
+
}
|
1803
|
+
|
1804
|
+
this.afterLoad( slide );
|
1805
|
+
|
1806
|
+
},
|
1807
|
+
|
1808
|
+
// Display error message
|
1809
|
+
// =====================
|
1810
|
+
|
1811
|
+
setError : function ( slide ) {
|
1812
|
+
|
1813
|
+
slide.hasError = true;
|
1814
|
+
|
1815
|
+
this.setContent( slide, slide.opts.errorTpl );
|
1816
|
+
|
1817
|
+
},
|
1818
|
+
|
1819
|
+
|
1820
|
+
showLoading : function( slide ) {
|
1821
|
+
var self = this;
|
1822
|
+
|
1823
|
+
slide = slide || self.current;
|
1824
|
+
|
1825
|
+
if ( slide && !slide.$spinner ) {
|
1826
|
+
slide.$spinner = $( self.opts.spinnerTpl ).appendTo( slide.$slide );
|
1827
|
+
}
|
1828
|
+
|
1829
|
+
},
|
1830
|
+
|
1831
|
+
hideLoading : function( slide ) {
|
1832
|
+
|
1833
|
+
var self = this;
|
1834
|
+
|
1835
|
+
slide = slide || self.current;
|
1836
|
+
|
1837
|
+
if ( slide && slide.$spinner ) {
|
1838
|
+
slide.$spinner.remove();
|
1839
|
+
|
1840
|
+
delete slide.$spinner;
|
1841
|
+
}
|
1842
|
+
|
1843
|
+
},
|
1844
|
+
|
1845
|
+
afterMove : function() {
|
1846
|
+
|
1847
|
+
var self = this;
|
1848
|
+
var current = self.current;
|
1849
|
+
var slides = {};
|
1850
|
+
|
1851
|
+
if ( !current ) {
|
1852
|
+
return;
|
1853
|
+
}
|
1854
|
+
|
1855
|
+
current.$slide.siblings().trigger( 'onReset' );
|
1856
|
+
|
1857
|
+
// Remove unnecessary slides
|
1858
|
+
$.each( self.slides, function( key, slide ) {
|
1859
|
+
|
1860
|
+
if ( slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1 ) {
|
1861
|
+
slides[ slide.pos ] = slide;
|
1862
|
+
|
1863
|
+
} else if ( slide ) {
|
1864
|
+
slide.$slide.remove();
|
1865
|
+
}
|
1866
|
+
|
1867
|
+
});
|
1868
|
+
|
1869
|
+
self.slides = slides;
|
1870
|
+
|
1871
|
+
self.trigger( 'afterMove' );
|
1872
|
+
|
1873
|
+
if ( current.isLoaded ) {
|
1874
|
+
self.complete();
|
1875
|
+
}
|
1876
|
+
|
1877
|
+
},
|
1878
|
+
|
1879
|
+
// Adjustments after slide has been loaded
|
1880
|
+
// =======================================
|
1881
|
+
|
1882
|
+
afterLoad : function( slide ) {
|
1883
|
+
|
1884
|
+
var self = this;
|
1885
|
+
|
1886
|
+
if ( self.isClosing ) {
|
1887
|
+
return;
|
1888
|
+
}
|
1889
|
+
|
1890
|
+
slide.isLoading = false;
|
1891
|
+
slide.isLoaded = true;
|
1892
|
+
|
1893
|
+
self.trigger( 'afterLoad', slide );
|
1894
|
+
|
1895
|
+
self.hideLoading( slide );
|
1896
|
+
|
1897
|
+
// Resize content to fit inside slide
|
1898
|
+
// Skip if slide has an $ghost element, because then it has been already processed
|
1899
|
+
if ( !slide.$ghost ) {
|
1900
|
+
self.updateSlide( slide, true );
|
1901
|
+
}
|
1902
|
+
|
1903
|
+
if ( slide.index === self.currIndex && slide.isMoved ) {
|
1904
|
+
self.complete();
|
1905
|
+
|
1906
|
+
} else if ( !slide.$ghost ) {
|
1907
|
+
self.revealImage( slide );
|
1908
|
+
}
|
1909
|
+
|
1910
|
+
},
|
1911
|
+
|
1912
|
+
|
1913
|
+
// Final adjustments after current gallery item is moved to position
|
1914
|
+
// and it`s content is loaded
|
1915
|
+
// ==================================================================
|
1916
|
+
|
1917
|
+
complete : function() {
|
1918
|
+
|
1919
|
+
var self = this;
|
1920
|
+
|
1921
|
+
var current = self.current;
|
1922
|
+
|
1923
|
+
self.revealImage( current, function() {
|
1924
|
+
current.isComplete = true;
|
1925
|
+
|
1926
|
+
current.$slide.addClass('fancybox-slide--complete');
|
1927
|
+
|
1928
|
+
self.updateCursor();
|
1929
|
+
|
1930
|
+
self.trigger( 'onComplete' );
|
1931
|
+
|
1932
|
+
// Try to focus on the first focusable element, skip for images and iframes
|
1933
|
+
if ( current.opts.focus && !( current.type === 'image' || current.type === 'iframe' ) ) {
|
1934
|
+
self.focus();
|
1935
|
+
}
|
1936
|
+
|
1937
|
+
});
|
1938
|
+
|
1939
|
+
},
|
1940
|
+
|
1941
|
+
|
1942
|
+
// Preload next and previous slides
|
1943
|
+
// ================================
|
1944
|
+
|
1945
|
+
preload : function() {
|
1946
|
+
var self = this;
|
1947
|
+
var next, prev;
|
1948
|
+
|
1949
|
+
if ( self.group.length < 2 ) {
|
1950
|
+
return;
|
1951
|
+
}
|
1952
|
+
|
1953
|
+
next = self.slides[ self.currPos + 1 ];
|
1954
|
+
prev = self.slides[ self.currPos - 1 ];
|
1955
|
+
|
1956
|
+
if ( next && next.type === 'image' ) {
|
1957
|
+
self.loadSlide( next );
|
1958
|
+
}
|
1959
|
+
|
1960
|
+
if ( prev && prev.type === 'image' ) {
|
1961
|
+
self.loadSlide( prev );
|
1962
|
+
}
|
1963
|
+
|
1964
|
+
},
|
1965
|
+
|
1966
|
+
|
1967
|
+
// Try to find and focus on the first focusable element
|
1968
|
+
// ====================================================
|
1969
|
+
|
1970
|
+
focus : function() {
|
1971
|
+
var current = this.current;
|
1972
|
+
var $el;
|
1973
|
+
|
1974
|
+
$el = current && current.isComplete ? current.$slide.find('button,:input,[tabindex],a:not(".disabled")').filter(':visible:first') : null;
|
1975
|
+
|
1976
|
+
if ( !$el || !$el.length ) {
|
1977
|
+
$el = this.$refs.container;
|
1978
|
+
}
|
1979
|
+
|
1980
|
+
$el.focus();
|
1981
|
+
|
1982
|
+
// Scroll position of wrapper element sometimes changes after focusing (IE)
|
1983
|
+
this.$refs.slider_wrap.scrollLeft(0);
|
1984
|
+
|
1985
|
+
// And the same goes for slide element
|
1986
|
+
if ( current ) {
|
1987
|
+
current.$slide.scrollTop(0);
|
1988
|
+
}
|
1989
|
+
|
1990
|
+
},
|
1991
|
+
|
1992
|
+
|
1993
|
+
// Activates current instance - brings container to the front and enables keyboard,
|
1994
|
+
// notifies other instances about deactivating
|
1995
|
+
// =================================================================================
|
1996
|
+
|
1997
|
+
activate : function () {
|
1998
|
+
var self = this;
|
1999
|
+
|
2000
|
+
// Deactivate all instances
|
2001
|
+
|
2002
|
+
$( '.fancybox-container' ).each(function () {
|
2003
|
+
var instance = $(this).data( 'FancyBox' );
|
2004
|
+
|
2005
|
+
// Skip self and closing instances
|
2006
|
+
|
2007
|
+
if (instance && instance.uid !== self.uid && !instance.isClosing) {
|
2008
|
+
instance.trigger( 'onDeactivate' );
|
2009
|
+
}
|
2010
|
+
|
2011
|
+
});
|
2012
|
+
|
2013
|
+
if ( self.current ) {
|
2014
|
+
|
2015
|
+
if ( self.$refs.container.index() > 0 ) {
|
2016
|
+
self.$refs.container.prependTo( document.body );
|
2017
|
+
}
|
2018
|
+
|
2019
|
+
self.updateControls();
|
2020
|
+
}
|
2021
|
+
|
2022
|
+
self.trigger( 'onActivate' );
|
2023
|
+
|
2024
|
+
self.addEvents();
|
2025
|
+
|
2026
|
+
},
|
2027
|
+
|
2028
|
+
|
2029
|
+
// Start closing procedure
|
2030
|
+
// This will start "zoom-out" animation if needed and clean everything up afterwards
|
2031
|
+
// =================================================================================
|
2032
|
+
|
2033
|
+
close : function( e ) {
|
2034
|
+
|
2035
|
+
var self = this;
|
2036
|
+
var current = self.current;
|
2037
|
+
var duration = current.opts.speed;
|
2038
|
+
|
2039
|
+
var done = $.proxy(function() {
|
2040
|
+
|
2041
|
+
self.cleanUp( e ); // Now "this" is again our instance
|
2042
|
+
|
2043
|
+
}, this);
|
2044
|
+
|
2045
|
+
if ( self.isAnimating || self.isClosing ) {
|
2046
|
+
return false;
|
2047
|
+
}
|
2048
|
+
|
2049
|
+
// If beforeClose callback prevents closing, make sure content is centered
|
2050
|
+
if ( self.trigger( 'beforeClose', e ) === false ) {
|
2051
|
+
$.fancybox.stop( self.$refs.slider );
|
2052
|
+
|
2053
|
+
requestAFrame(function() {
|
2054
|
+
self.update( true, true, 150 );
|
2055
|
+
});
|
2056
|
+
|
2057
|
+
return;
|
2058
|
+
}
|
2059
|
+
|
2060
|
+
self.isClosing = true;
|
2061
|
+
|
2062
|
+
if ( current.timouts ) {
|
2063
|
+
clearTimeout( current.timouts );
|
2064
|
+
}
|
2065
|
+
|
2066
|
+
if ( e !== true) {
|
2067
|
+
$.fancybox.stop( self.$refs.slider );
|
2068
|
+
}
|
2069
|
+
|
2070
|
+
self.$refs.container
|
2071
|
+
.removeClass('fancybox-container--active')
|
2072
|
+
.addClass('fancybox-container--closing');
|
2073
|
+
|
2074
|
+
current.$slide
|
2075
|
+
.removeClass('fancybox-slide--complete')
|
2076
|
+
.siblings()
|
2077
|
+
.remove();
|
2078
|
+
|
2079
|
+
|
2080
|
+
if ( !current.isMoved ) {
|
2081
|
+
current.$slide.css('overflow', 'visible');
|
2082
|
+
}
|
2083
|
+
|
2084
|
+
// Remove all events
|
2085
|
+
// If there are multiple instances, they will be set again by "activate" method
|
2086
|
+
|
2087
|
+
self.removeEvents();
|
2088
|
+
|
2089
|
+
// Clean up
|
2090
|
+
|
2091
|
+
self.hideLoading( current );
|
2092
|
+
|
2093
|
+
self.hideControls();
|
2094
|
+
|
2095
|
+
self.updateCursor();
|
2096
|
+
|
2097
|
+
self.$refs.bg.css('transition-duration', duration + 'ms');
|
2098
|
+
|
2099
|
+
this.$refs.container.removeClass( 'fancybox-container--ready' );
|
2100
|
+
|
2101
|
+
if ( e === true ) {
|
2102
|
+
setTimeout( done, duration );
|
2103
|
+
|
2104
|
+
} else if ( !self.zoomInOut( 'Out', duration, done ) ) {
|
2105
|
+
$.fancybox.animate( self.$refs.container, null, { opacity : 0 }, duration, "easeInSine", done );
|
2106
|
+
}
|
2107
|
+
|
2108
|
+
},
|
2109
|
+
|
2110
|
+
|
2111
|
+
// Final adjustments after removing the instance
|
2112
|
+
// =============================================
|
2113
|
+
|
2114
|
+
cleanUp : function( e ) {
|
2115
|
+
var self = this,
|
2116
|
+
instance;
|
2117
|
+
|
2118
|
+
self.$refs.slider.children().trigger( 'onReset' );
|
2119
|
+
|
2120
|
+
self.$refs.container.empty().remove();
|
2121
|
+
|
2122
|
+
self.trigger( 'afterClose', e );
|
2123
|
+
|
2124
|
+
self.current = null;
|
2125
|
+
|
2126
|
+
// Check if there are other instances
|
2127
|
+
instance = $.fancybox.getInstance();
|
2128
|
+
|
2129
|
+
if ( instance ) {
|
2130
|
+
instance.activate();
|
2131
|
+
|
2132
|
+
} else {
|
2133
|
+
|
2134
|
+
$( 'html' ).removeClass( 'fancybox-enabled' );
|
2135
|
+
$( 'body' ).removeAttr( 'style' );
|
2136
|
+
|
2137
|
+
$W.scrollTop( self.scrollTop ).scrollLeft( self.scrollLeft );
|
2138
|
+
|
2139
|
+
$( '#fancybox-noscroll' ).remove();
|
2140
|
+
|
2141
|
+
}
|
2142
|
+
|
2143
|
+
// Place back focus
|
2144
|
+
if ( self.$lastFocus ) {
|
2145
|
+
self.$lastFocus.focus();
|
2146
|
+
}
|
2147
|
+
|
2148
|
+
},
|
2149
|
+
|
2150
|
+
|
2151
|
+
// Call callback and trigger an event
|
2152
|
+
// ==================================
|
2153
|
+
|
2154
|
+
trigger : function( name, slide ) {
|
2155
|
+
var args = Array.prototype.slice.call(arguments, 1),
|
2156
|
+
self = this,
|
2157
|
+
obj = slide && slide.opts ? slide : self.current,
|
2158
|
+
rez;
|
2159
|
+
|
2160
|
+
if ( obj ) {
|
2161
|
+
args.unshift( obj );
|
2162
|
+
|
2163
|
+
} else {
|
2164
|
+
obj = self;
|
2165
|
+
}
|
2166
|
+
|
2167
|
+
args.unshift( self );
|
2168
|
+
|
2169
|
+
if ( $.isFunction( obj.opts[ name ] ) ) {
|
2170
|
+
rez = obj.opts[ name ].apply( obj, args );
|
2171
|
+
}
|
2172
|
+
|
2173
|
+
if ( rez === false ) {
|
2174
|
+
return rez;
|
2175
|
+
}
|
2176
|
+
|
2177
|
+
if ( name === 'afterClose' ) {
|
2178
|
+
$( document ).trigger( name + '.fb', args );
|
2179
|
+
|
2180
|
+
} else {
|
2181
|
+
self.$refs.container.trigger( name + '.fb', args );
|
2182
|
+
}
|
2183
|
+
|
2184
|
+
},
|
2185
|
+
|
2186
|
+
|
2187
|
+
// Toggle toolbar and caption
|
2188
|
+
// ==========================
|
2189
|
+
|
2190
|
+
toggleControls : function( force ) {
|
2191
|
+
|
2192
|
+
if ( this.isHiddenControls ) {
|
2193
|
+
this.updateControls( force );
|
2194
|
+
|
2195
|
+
} else {
|
2196
|
+
this.hideControls();
|
2197
|
+
}
|
2198
|
+
|
2199
|
+
|
2200
|
+
},
|
2201
|
+
|
2202
|
+
|
2203
|
+
// Hide toolbar and caption
|
2204
|
+
// ========================
|
2205
|
+
|
2206
|
+
hideControls : function () {
|
2207
|
+
|
2208
|
+
this.isHiddenControls = true;
|
2209
|
+
|
2210
|
+
this.$refs.container.removeClass('fancybox-show-controls');
|
2211
|
+
|
2212
|
+
this.$refs.container.removeClass('fancybox-show-caption');
|
2213
|
+
|
2214
|
+
},
|
2215
|
+
|
2216
|
+
|
2217
|
+
// Update infobar values, navigation button states and reveal caption
|
2218
|
+
// ==================================================================
|
2219
|
+
|
2220
|
+
updateControls : function ( force ) {
|
2221
|
+
|
2222
|
+
var self = this;
|
2223
|
+
|
2224
|
+
var $container = self.$refs.container;
|
2225
|
+
var $caption = self.$refs.caption;
|
2226
|
+
|
2227
|
+
// Toggle infobar and buttons
|
2228
|
+
|
2229
|
+
var current = self.current;
|
2230
|
+
var index = current.index;
|
2231
|
+
var opts = current.opts;
|
2232
|
+
var caption = opts.caption;
|
2233
|
+
|
2234
|
+
if ( this.isHiddenControls && force !== true ) {
|
2235
|
+
return;
|
2236
|
+
}
|
2237
|
+
|
2238
|
+
this.isHiddenControls = false;
|
2239
|
+
|
2240
|
+
$container
|
2241
|
+
.addClass('fancybox-show-controls')
|
2242
|
+
.toggleClass('fancybox-show-infobar', !!opts.infobar && self.group.length > 1)
|
2243
|
+
.toggleClass('fancybox-show-buttons', !!opts.buttons )
|
2244
|
+
.toggleClass('fancybox-is-modal', !!opts.modal );
|
2245
|
+
|
2246
|
+
$('.fancybox-button--left', $container).toggleClass( 'fancybox-button--disabled', (!opts.loop && index <= 0 ) );
|
2247
|
+
$('.fancybox-button--right', $container).toggleClass( 'fancybox-button--disabled', (!opts.loop && index >= self.group.length - 1) );
|
2248
|
+
|
2249
|
+
$('.fancybox-button--play', $container).toggle( !!( opts.slideShow && self.group.length > 1) );
|
2250
|
+
$('.fancybox-button--close', $container).toggle( !!opts.closeBtn );
|
2251
|
+
|
2252
|
+
// Update infobar values
|
2253
|
+
|
2254
|
+
$('.js-fancybox-count', $container).html( self.group.length );
|
2255
|
+
$('.js-fancybox-index', $container).html( index + 1 );
|
2256
|
+
|
2257
|
+
// Recalculate content dimensions
|
2258
|
+
current.$slide.trigger( 'refresh' );
|
2259
|
+
|
2260
|
+
// Reveal or create new caption
|
2261
|
+
if ( $caption ) {
|
2262
|
+
$caption.empty();
|
2263
|
+
}
|
2264
|
+
|
2265
|
+
if ( caption && caption.length ) {
|
2266
|
+
$caption.html( caption );
|
2267
|
+
|
2268
|
+
this.$refs.container.addClass( 'fancybox-show-caption ');
|
2269
|
+
|
2270
|
+
self.$caption = $caption;
|
2271
|
+
|
2272
|
+
} else {
|
2273
|
+
this.$refs.container.removeClass( 'fancybox-show-caption' );
|
2274
|
+
}
|
2275
|
+
|
2276
|
+
}
|
2277
|
+
|
2278
|
+
});
|
2279
|
+
|
2280
|
+
|
2281
|
+
$.fancybox = {
|
2282
|
+
|
2283
|
+
version : "3.0.47",
|
2284
|
+
defaults : defaults,
|
2285
|
+
|
2286
|
+
|
2287
|
+
// Get current instance and execute a command.
|
2288
|
+
//
|
2289
|
+
// Examples of usage:
|
2290
|
+
//
|
2291
|
+
// $instance = $.fancybox.getInstance();
|
2292
|
+
// $.fancybox.getInstance().jumpTo( 1 );
|
2293
|
+
// $.fancybox.getInstance( 'jumpTo', 1 );
|
2294
|
+
// $.fancybox.getInstance( function() {
|
2295
|
+
// console.info( this.currIndex );
|
2296
|
+
// });
|
2297
|
+
// ======================================================
|
2298
|
+
|
2299
|
+
getInstance : function ( command ) {
|
2300
|
+
var instance = $('.fancybox-container:not(".fancybox-container--closing"):first').data( 'FancyBox' );
|
2301
|
+
var args = Array.prototype.slice.call(arguments, 1);
|
2302
|
+
|
2303
|
+
if ( instance instanceof FancyBox ) {
|
2304
|
+
|
2305
|
+
if ( $.type( command ) === 'string' ) {
|
2306
|
+
instance[ command ].apply( instance, args );
|
2307
|
+
|
2308
|
+
} else if ( $.type( command ) === 'function' ) {
|
2309
|
+
command.apply( instance, args );
|
2310
|
+
|
2311
|
+
}
|
2312
|
+
|
2313
|
+
return instance;
|
2314
|
+
}
|
2315
|
+
|
2316
|
+
return false;
|
2317
|
+
|
2318
|
+
},
|
2319
|
+
|
2320
|
+
|
2321
|
+
// Create new instance
|
2322
|
+
// ===================
|
2323
|
+
|
2324
|
+
open : function ( items, opts, index ) {
|
2325
|
+
return new FancyBox( items, opts, index );
|
2326
|
+
},
|
2327
|
+
|
2328
|
+
|
2329
|
+
// Close current or all instances
|
2330
|
+
// ==============================
|
2331
|
+
|
2332
|
+
close : function ( all ) {
|
2333
|
+
var instance = this.getInstance();
|
2334
|
+
|
2335
|
+
if ( instance ) {
|
2336
|
+
instance.close();
|
2337
|
+
|
2338
|
+
// Try to find and close next instance
|
2339
|
+
|
2340
|
+
if ( all === true ) {
|
2341
|
+
this.close();
|
2342
|
+
}
|
2343
|
+
}
|
2344
|
+
|
2345
|
+
},
|
2346
|
+
|
2347
|
+
|
2348
|
+
// Test for the existence of touch events in the browser
|
2349
|
+
// Limit to mobile devices
|
2350
|
+
// ====================================================
|
2351
|
+
|
2352
|
+
isTouch : document.createTouch !== undefined && /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent),
|
2353
|
+
|
2354
|
+
|
2355
|
+
// Detect if 'translate3d' support is available
|
2356
|
+
// ============================================
|
2357
|
+
|
2358
|
+
use3d : (function() {
|
2359
|
+
var div = document.createElement('div');
|
2360
|
+
|
2361
|
+
return window.getComputedStyle( div ).getPropertyValue('transform') && !(document.documentMode && document.documentMode <= 11);
|
2362
|
+
}()),
|
2363
|
+
|
2364
|
+
|
2365
|
+
// Helper function to get current visual state of an element
|
2366
|
+
// returns array[ top, left, horizontal-scale, vertical-scale, opacity ]
|
2367
|
+
// =====================================================================
|
2368
|
+
|
2369
|
+
getTranslate : function( $el ) {
|
2370
|
+
var position, matrix;
|
2371
|
+
|
2372
|
+
if ( !$el || !$el.length ) {
|
2373
|
+
return false;
|
2374
|
+
}
|
2375
|
+
|
2376
|
+
position = $el.get( 0 ).getBoundingClientRect();
|
2377
|
+
matrix = $el.eq( 0 ).css('transform');
|
2378
|
+
|
2379
|
+
if ( matrix && matrix.indexOf( 'matrix' ) !== -1 ) {
|
2380
|
+
matrix = matrix.split('(')[1];
|
2381
|
+
matrix = matrix.split(')')[0];
|
2382
|
+
matrix = matrix.split(',');
|
2383
|
+
} else {
|
2384
|
+
matrix = [];
|
2385
|
+
}
|
2386
|
+
|
2387
|
+
if ( matrix.length ) {
|
2388
|
+
|
2389
|
+
// If IE
|
2390
|
+
if ( matrix.length > 10 ) {
|
2391
|
+
matrix = [ matrix[13], matrix[12], matrix[0], matrix[5] ];
|
2392
|
+
|
2393
|
+
} else {
|
2394
|
+
matrix = [ matrix[5], matrix[4], matrix[0], matrix[3]];
|
2395
|
+
}
|
2396
|
+
|
2397
|
+
matrix = matrix.map(parseFloat);
|
2398
|
+
|
2399
|
+
} else {
|
2400
|
+
matrix = [ 0, 0, 1, 1 ];
|
2401
|
+
}
|
2402
|
+
|
2403
|
+
return {
|
2404
|
+
top : matrix[ 0 ],
|
2405
|
+
left : matrix[ 1 ],
|
2406
|
+
scaleX : matrix[ 2 ],
|
2407
|
+
scaleY : matrix[ 3 ],
|
2408
|
+
opacity : parseFloat( $el.css('opacity') ),
|
2409
|
+
width : position.width,
|
2410
|
+
height : position.height
|
2411
|
+
};
|
2412
|
+
|
2413
|
+
},
|
2414
|
+
|
2415
|
+
|
2416
|
+
// Shortcut for setting "translate3d" properties for element
|
2417
|
+
// Can set be used to set opacity, too
|
2418
|
+
// ========================================================
|
2419
|
+
|
2420
|
+
setTranslate : function( $el, props ) {
|
2421
|
+
var str = '';
|
2422
|
+
var css = {};
|
2423
|
+
|
2424
|
+
if ( !$el || !props ) {
|
2425
|
+
return;
|
2426
|
+
}
|
2427
|
+
|
2428
|
+
if ( props.left !== undefined || props.top !== undefined ) {
|
2429
|
+
|
2430
|
+
str = ( props.left === undefined ? $el.position().top : props.left ) + 'px, ' + ( props.top === undefined ? $el.position().top : props.top ) + 'px';
|
2431
|
+
|
2432
|
+
if ( this.use3d ) {
|
2433
|
+
str = 'translate3d(' + str + ', 0px)';
|
2434
|
+
|
2435
|
+
} else {
|
2436
|
+
str = 'translate(' + str + ')';
|
2437
|
+
}
|
2438
|
+
|
2439
|
+
}
|
2440
|
+
|
2441
|
+
if ( props.scaleX !== undefined && props.scaleY !== undefined ) {
|
2442
|
+
str = (str.length ? str + ' ' : '') + 'scale(' + props.scaleX + ', ' + props.scaleY + ')';
|
2443
|
+
}
|
2444
|
+
|
2445
|
+
if ( str.length ) {
|
2446
|
+
css.transform = str;
|
2447
|
+
}
|
2448
|
+
|
2449
|
+
if ( props.opacity !== undefined ) {
|
2450
|
+
css.opacity = props.opacity;
|
2451
|
+
}
|
2452
|
+
|
2453
|
+
if ( props.width !== undefined ) {
|
2454
|
+
css.width = props.width;
|
2455
|
+
}
|
2456
|
+
|
2457
|
+
if ( props.height !== undefined ) {
|
2458
|
+
css.height = props.height;
|
2459
|
+
}
|
2460
|
+
|
2461
|
+
return $el.css( css );
|
2462
|
+
|
2463
|
+
},
|
2464
|
+
|
2465
|
+
|
2466
|
+
// Common easings for entrances and exits
|
2467
|
+
// t: current time, b: begInnIng value, c: change In value, d: duration
|
2468
|
+
// ====================================================================
|
2469
|
+
|
2470
|
+
easing : {
|
2471
|
+
easeOutCubic : function (t, b, c, d) {
|
2472
|
+
return c * ((t=t/d-1)*t*t + 1) + b;
|
2473
|
+
},
|
2474
|
+
easeInCubic : function (t, b, c, d) {
|
2475
|
+
return c * (t/=d)*t*t + b;
|
2476
|
+
},
|
2477
|
+
easeOutSine : function (t, b, c, d) {
|
2478
|
+
return c * Math.sin(t/d * (Math.PI/2)) + b;
|
2479
|
+
},
|
2480
|
+
easeInSine : function (t, b, c, d) {
|
2481
|
+
return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
|
2482
|
+
}
|
2483
|
+
},
|
2484
|
+
|
2485
|
+
|
2486
|
+
// Stop fancyBox animation
|
2487
|
+
// =======================
|
2488
|
+
|
2489
|
+
stop : function( $el ) {
|
2490
|
+
|
2491
|
+
$el.removeData( 'animateID' );
|
2492
|
+
|
2493
|
+
},
|
2494
|
+
|
2495
|
+
// Animate element using "translate3d"
|
2496
|
+
// Usage:
|
2497
|
+
// animate( element, start properties, end properties, duration, easing, callback )
|
2498
|
+
// or
|
2499
|
+
// animate( element, start properties, end properties, duration, callback )
|
2500
|
+
// =================================================================================
|
2501
|
+
|
2502
|
+
animate : function( $el, from, to, duration, easing, done ) {
|
2503
|
+
|
2504
|
+
var self = this;
|
2505
|
+
|
2506
|
+
var lastTime = null;
|
2507
|
+
var animTime = 0;
|
2508
|
+
|
2509
|
+
var curr;
|
2510
|
+
var diff;
|
2511
|
+
var id;
|
2512
|
+
|
2513
|
+
var finish = function() {
|
2514
|
+
if ( to.scaleX !== undefined && to.scaleY !== undefined && from && from.width !== undefined && from.height !== undefined ) {
|
2515
|
+
to.width = from.width * to.scaleX;
|
2516
|
+
to.height = from.height * to.scaleY;
|
2517
|
+
|
2518
|
+
to.scaleX = 1;
|
2519
|
+
to.scaleY = 1;
|
2520
|
+
}
|
2521
|
+
|
2522
|
+
self.setTranslate( $el, to );
|
2523
|
+
|
2524
|
+
done();
|
2525
|
+
};
|
2526
|
+
|
2527
|
+
var frame = function ( timestamp ) {
|
2528
|
+
curr = [];
|
2529
|
+
diff = 0;
|
2530
|
+
|
2531
|
+
// If "stop" method has been called on this element, then just stop
|
2532
|
+
if ( !$el.length || $el.data( 'animateID' ) !== id ) {
|
2533
|
+
return;
|
2534
|
+
}
|
2535
|
+
|
2536
|
+
timestamp = timestamp || Date.now();
|
2537
|
+
|
2538
|
+
if ( lastTime ) {
|
2539
|
+
diff = timestamp - lastTime;
|
2540
|
+
}
|
2541
|
+
|
2542
|
+
lastTime = timestamp;
|
2543
|
+
animTime += diff;
|
2544
|
+
|
2545
|
+
// Are we done?
|
2546
|
+
if ( animTime >= duration ) {
|
2547
|
+
|
2548
|
+
finish();
|
2549
|
+
|
2550
|
+
return;
|
2551
|
+
}
|
2552
|
+
|
2553
|
+
for ( var prop in to ) {
|
2554
|
+
|
2555
|
+
if ( to.hasOwnProperty( prop ) && from[ prop ] !== undefined ) {
|
2556
|
+
|
2557
|
+
if ( from[ prop ] == to[ prop ] ) {
|
2558
|
+
curr[ prop ] = to[ prop ];
|
2559
|
+
|
2560
|
+
} else {
|
2561
|
+
curr[ prop ] = self.easing[ easing ]( animTime, from[ prop ], to[ prop ] - from[ prop ], duration );
|
2562
|
+
}
|
2563
|
+
|
2564
|
+
}
|
2565
|
+
}
|
2566
|
+
|
2567
|
+
self.setTranslate( $el, curr );
|
2568
|
+
|
2569
|
+
requestAFrame( frame );
|
2570
|
+
};
|
2571
|
+
|
2572
|
+
self.animateID = id = self.animateID === undefined ? 1 : self.animateID + 1;
|
2573
|
+
|
2574
|
+
$el.data( 'animateID', id );
|
2575
|
+
|
2576
|
+
if ( done === undefined && $.type(easing) == 'function' ) {
|
2577
|
+
done = easing;
|
2578
|
+
easing = undefined;
|
2579
|
+
}
|
2580
|
+
|
2581
|
+
if ( !easing ) {
|
2582
|
+
easing = "easeOutCubic";
|
2583
|
+
}
|
2584
|
+
|
2585
|
+
done = done || $.noop;
|
2586
|
+
|
2587
|
+
if ( from ) {
|
2588
|
+
this.setTranslate( $el, from );
|
2589
|
+
|
2590
|
+
} else {
|
2591
|
+
|
2592
|
+
// We need current values to calculate change in time
|
2593
|
+
from = this.getTranslate( $el );
|
2594
|
+
}
|
2595
|
+
|
2596
|
+
if ( duration ) {
|
2597
|
+
$el.show();
|
2598
|
+
|
2599
|
+
requestAFrame( frame );
|
2600
|
+
|
2601
|
+
} else {
|
2602
|
+
finish();
|
2603
|
+
}
|
2604
|
+
|
2605
|
+
}
|
2606
|
+
|
2607
|
+
};
|
2608
|
+
|
2609
|
+
|
2610
|
+
// Event handler for click event to "fancyboxed" links
|
2611
|
+
// ===================================================
|
2612
|
+
|
2613
|
+
function _run( e ) {
|
2614
|
+
var target = e.currentTarget,
|
2615
|
+
opts = e.data ? e.data.options : {},
|
2616
|
+
items = e.data ? e.data.items : [],
|
2617
|
+
value = '',
|
2618
|
+
index = 0;
|
2619
|
+
|
2620
|
+
e.preventDefault();
|
2621
|
+
e.stopPropagation();
|
2622
|
+
|
2623
|
+
// Get all related items and find index for clicked one
|
2624
|
+
|
2625
|
+
if ( $(target).attr( 'data-fancybox' ) ) {
|
2626
|
+
value = $(target).data( 'fancybox' );
|
2627
|
+
}
|
2628
|
+
|
2629
|
+
if ( value ) {
|
2630
|
+
items = items.length ? items.filter( '[data-fancybox="' + value + '"]' ) : $( '[data-fancybox=' + value + ']' );
|
2631
|
+
index = items.index( target );
|
2632
|
+
|
2633
|
+
} else {
|
2634
|
+
items = [ target ];
|
2635
|
+
}
|
2636
|
+
|
2637
|
+
$.fancybox.open( items, opts, index );
|
2638
|
+
}
|
2639
|
+
|
2640
|
+
|
2641
|
+
// Create a jQuery plugin
|
2642
|
+
// ======================
|
2643
|
+
|
2644
|
+
$.fn.fancybox = function (options) {
|
2645
|
+
|
2646
|
+
this.off('click.fb-start').on('click.fb-start', {
|
2647
|
+
items : this,
|
2648
|
+
options : options || {}
|
2649
|
+
}, _run);
|
2650
|
+
|
2651
|
+
return this;
|
2652
|
+
|
2653
|
+
};
|
2654
|
+
|
2655
|
+
|
2656
|
+
// Self initializing plugin
|
2657
|
+
// ========================
|
2658
|
+
|
2659
|
+
$(document).on('click.fb-start', '[data-fancybox]', _run);
|
2660
|
+
|
2661
|
+
}(window, document, window.jQuery));
|
2662
|
+
|
2663
|
+
// ==========================================================================
|
2664
|
+
//
|
2665
|
+
// Media
|
2666
|
+
// Adds additional media type support
|
2667
|
+
//
|
2668
|
+
// ==========================================================================
|
2669
|
+
;(function ($) {
|
2670
|
+
|
2671
|
+
'use strict';
|
2672
|
+
|
2673
|
+
// Formats matching url to final form
|
2674
|
+
|
2675
|
+
var format = function (url, rez, params) {
|
2676
|
+
if ( !url ) {
|
2677
|
+
return;
|
2678
|
+
}
|
2679
|
+
|
2680
|
+
params = params || '';
|
2681
|
+
|
2682
|
+
if ( $.type(params) === "object" ) {
|
2683
|
+
params = $.param(params, true);
|
2684
|
+
}
|
2685
|
+
|
2686
|
+
$.each(rez, function (key, value) {
|
2687
|
+
url = url.replace('$' + key, value || '');
|
2688
|
+
});
|
2689
|
+
|
2690
|
+
if (params.length) {
|
2691
|
+
url += (url.indexOf('?') > 0 ? '&' : '?') + params;
|
2692
|
+
}
|
2693
|
+
|
2694
|
+
return url;
|
2695
|
+
};
|
2696
|
+
|
2697
|
+
// Object containing properties for each media type
|
2698
|
+
|
2699
|
+
var media = {
|
2700
|
+
youtube: {
|
2701
|
+
matcher: /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
|
2702
|
+
params: {
|
2703
|
+
autoplay: 1,
|
2704
|
+
autohide: 1,
|
2705
|
+
fs: 1,
|
2706
|
+
rel: 0,
|
2707
|
+
hd: 1,
|
2708
|
+
wmode: 'transparent',
|
2709
|
+
enablejsapi: 1,
|
2710
|
+
html5: 1
|
2711
|
+
},
|
2712
|
+
paramPlace : 8,
|
2713
|
+
type: 'iframe',
|
2714
|
+
url: '//www.youtube.com/embed/$4',
|
2715
|
+
thumb: '//img.youtube.com/vi/$4/hqdefault.jpg'
|
2716
|
+
},
|
2717
|
+
|
2718
|
+
vimeo: {
|
2719
|
+
matcher: /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,
|
2720
|
+
params: {
|
2721
|
+
autoplay: 1,
|
2722
|
+
hd: 1,
|
2723
|
+
show_title: 1,
|
2724
|
+
show_byline: 1,
|
2725
|
+
show_portrait: 0,
|
2726
|
+
fullscreen: 1,
|
2727
|
+
api: 1
|
2728
|
+
},
|
2729
|
+
paramPlace : 3,
|
2730
|
+
type: 'iframe',
|
2731
|
+
url: '//player.vimeo.com/video/$2'
|
2732
|
+
},
|
2733
|
+
|
2734
|
+
metacafe: {
|
2735
|
+
matcher: /metacafe.com\/watch\/(\d+)\/(.*)?/,
|
2736
|
+
type: 'iframe',
|
2737
|
+
url: '//www.metacafe.com/embed/$1/?ap=1'
|
2738
|
+
},
|
2739
|
+
|
2740
|
+
dailymotion: {
|
2741
|
+
matcher: /dailymotion.com\/video\/(.*)\/?(.*)/,
|
2742
|
+
params: {
|
2743
|
+
additionalInfos: 0,
|
2744
|
+
autoStart: 1
|
2745
|
+
},
|
2746
|
+
type: 'iframe',
|
2747
|
+
url: '//www.dailymotion.com/embed/video/$1'
|
2748
|
+
},
|
2749
|
+
|
2750
|
+
vine: {
|
2751
|
+
matcher: /vine.co\/v\/([a-zA-Z0-9\?\=\-]+)/,
|
2752
|
+
type: 'iframe',
|
2753
|
+
url: '//vine.co/v/$1/embed/simple'
|
2754
|
+
},
|
2755
|
+
|
2756
|
+
instagram: {
|
2757
|
+
matcher: /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
|
2758
|
+
type: 'image',
|
2759
|
+
url: '//$1/p/$2/media/?size=l'
|
2760
|
+
},
|
2761
|
+
|
2762
|
+
// Examples:
|
2763
|
+
// http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
|
2764
|
+
// http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
|
2765
|
+
// https://www.google.lv/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572
|
2766
|
+
google_maps: {
|
2767
|
+
matcher: /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,
|
2768
|
+
type: 'iframe',
|
2769
|
+
url: function (rez) {
|
2770
|
+
return '//maps.google.' + rez[2] + '/?ll=' + ( rez[9] ? rez[9] + '&z=' + Math.floor( rez[10] ) + ( rez[12] ? rez[12].replace(/^\//, "&") : '' ) : rez[12] ) + '&output=' + ( rez[12] && rez[12].indexOf('layer=c') > 0 ? 'svembed' : 'embed' );
|
2771
|
+
}
|
2772
|
+
}
|
2773
|
+
};
|
2774
|
+
|
2775
|
+
$(document).on('onInit.fb', function (e, instance) {
|
2776
|
+
|
2777
|
+
$.each(instance.group, function( i, item ) {
|
2778
|
+
|
2779
|
+
var url = item.src || '',
|
2780
|
+
type = false,
|
2781
|
+
thumb,
|
2782
|
+
rez,
|
2783
|
+
params,
|
2784
|
+
urlParams,
|
2785
|
+
o,
|
2786
|
+
provider;
|
2787
|
+
|
2788
|
+
// Skip items that already have content type
|
2789
|
+
if ( item.type ) {
|
2790
|
+
return;
|
2791
|
+
}
|
2792
|
+
|
2793
|
+
// Look for any matching media type
|
2794
|
+
|
2795
|
+
$.each(media, function ( n, el ) {
|
2796
|
+
rez = url.match(el.matcher);
|
2797
|
+
o = {};
|
2798
|
+
provider = n;
|
2799
|
+
|
2800
|
+
if (!rez) {
|
2801
|
+
return;
|
2802
|
+
}
|
2803
|
+
|
2804
|
+
type = el.type;
|
2805
|
+
|
2806
|
+
if ( el.paramPlace && rez[ el.paramPlace ] ) {
|
2807
|
+
urlParams = rez[ el.paramPlace ];
|
2808
|
+
|
2809
|
+
if ( urlParams[ 0 ] == '?' ) {
|
2810
|
+
urlParams = urlParams.substring(1);
|
2811
|
+
}
|
2812
|
+
|
2813
|
+
urlParams = urlParams.split('&');
|
2814
|
+
|
2815
|
+
for ( var m = 0; m < urlParams.length; ++m ) {
|
2816
|
+
var p = urlParams[ m ].split('=', 2);
|
2817
|
+
|
2818
|
+
if ( p.length == 2 ) {
|
2819
|
+
o[ p[0] ] = decodeURIComponent( p[1].replace(/\+/g, " ") );
|
2820
|
+
}
|
2821
|
+
}
|
2822
|
+
}
|
2823
|
+
|
2824
|
+
params = $.extend( true, {}, el.params, item.opts[ n ], o );
|
2825
|
+
|
2826
|
+
url = $.type(el.url) === "function" ? el.url.call(this, rez, params, item) : format(el.url, rez, params);
|
2827
|
+
thumb = $.type(el.thumb) === "function" ? el.thumb.call(this, rez, params, item) : format(el.thumb, rez);
|
2828
|
+
|
2829
|
+
if ( provider === 'vimeo' ) {
|
2830
|
+
url = url.replace('&%23', '#');
|
2831
|
+
}
|
2832
|
+
|
2833
|
+
return false;
|
2834
|
+
});
|
2835
|
+
|
2836
|
+
// If it is found, then change content type and update the url
|
2837
|
+
|
2838
|
+
if ( type ) {
|
2839
|
+
item.src = url;
|
2840
|
+
item.type = type;
|
2841
|
+
|
2842
|
+
if ( !item.opts.thumb && !(item.opts.$thumb && item.opts.$thumb.length ) ) {
|
2843
|
+
item.opts.thumb = thumb;
|
2844
|
+
}
|
2845
|
+
|
2846
|
+
if ( type === 'iframe' ) {
|
2847
|
+
$.extend(true, item.opts, {
|
2848
|
+
iframe : {
|
2849
|
+
preload : false,
|
2850
|
+
scrolling : "no"
|
2851
|
+
},
|
2852
|
+
smallBtn : false,
|
2853
|
+
closeBtn : true,
|
2854
|
+
fullScreen : false,
|
2855
|
+
slideShow : false
|
2856
|
+
});
|
2857
|
+
|
2858
|
+
item.opts.slideClass += ' fancybox-slide--video';
|
2859
|
+
}
|
2860
|
+
|
2861
|
+
} else {
|
2862
|
+
|
2863
|
+
// If no content type is found, then set it to `iframe` as fallback
|
2864
|
+
item.type = 'iframe';
|
2865
|
+
|
2866
|
+
}
|
2867
|
+
|
2868
|
+
});
|
2869
|
+
|
2870
|
+
});
|
2871
|
+
|
2872
|
+
}(window.jQuery));
|
2873
|
+
|
2874
|
+
// ==========================================================================
|
2875
|
+
//
|
2876
|
+
// Guestures
|
2877
|
+
// Adds touch guestures, handles click and tap events
|
2878
|
+
//
|
2879
|
+
// ==========================================================================
|
2880
|
+
;(function (window, document, $) {
|
2881
|
+
'use strict';
|
2882
|
+
|
2883
|
+
var requestAFrame = (function() {
|
2884
|
+
return window.requestAnimationFrame ||
|
2885
|
+
window.webkitRequestAnimationFrame ||
|
2886
|
+
window.mozRequestAnimationFrame ||
|
2887
|
+
function( callback ) {
|
2888
|
+
window.setTimeout(callback, 1000 / 60); };
|
2889
|
+
})();
|
2890
|
+
|
2891
|
+
|
2892
|
+
var pointers = function( e ) {
|
2893
|
+
var result = [];
|
2894
|
+
|
2895
|
+
e = e.originalEvent || e || window.e;
|
2896
|
+
e = e.touches && e.touches.length ? e.touches : ( e.changedTouches && e.changedTouches.length ? e.changedTouches : [ e ] );
|
2897
|
+
|
2898
|
+
for ( var key in e ) {
|
2899
|
+
|
2900
|
+
if ( e[ key ].pageX ) {
|
2901
|
+
result.push( { x : e[ key ].pageX, y : e[ key ].pageY } );
|
2902
|
+
|
2903
|
+
} else if ( e[ key ].clientX ) {
|
2904
|
+
result.push( { x : e[ key ].clientX, y : e[ key ].clientY } );
|
2905
|
+
}
|
2906
|
+
}
|
2907
|
+
|
2908
|
+
return result;
|
2909
|
+
};
|
2910
|
+
|
2911
|
+
var distance = function( point2, point1, what ) {
|
2912
|
+
|
2913
|
+
if ( !point1 || !point2 ) {
|
2914
|
+
return 0;
|
2915
|
+
}
|
2916
|
+
|
2917
|
+
if ( what === 'x' ) {
|
2918
|
+
return point2.x - point1.x;
|
2919
|
+
|
2920
|
+
} else if ( what === 'y' ) {
|
2921
|
+
return point2.y - point1.y;
|
2922
|
+
}
|
2923
|
+
|
2924
|
+
return Math.sqrt( Math.pow( point2.x - point1.x, 2 ) + Math.pow( point2.y - point1.y, 2 ) );
|
2925
|
+
|
2926
|
+
};
|
2927
|
+
|
2928
|
+
var isClickable = function( $el ) {
|
2929
|
+
|
2930
|
+
return $el.is('a') || $el.is('button') || $el.is('input') || $el.is('select') || $el.is('textarea') || $.isFunction( $el.get(0).onclick );
|
2931
|
+
|
2932
|
+
};
|
2933
|
+
|
2934
|
+
var hasScrollbars = function( el ) {
|
2935
|
+
var overflowY = window.getComputedStyle( el )['overflow-y'];
|
2936
|
+
var overflowX = window.getComputedStyle( el )['overflow-x'];
|
2937
|
+
|
2938
|
+
var vertical = (overflowY === 'scroll' || overflowY === 'auto') && el.scrollHeight > el.clientHeight;
|
2939
|
+
var horizontal = (overflowX === 'scroll' || overflowX === 'auto') && el.scrollWidth > el.clientWidth;
|
2940
|
+
|
2941
|
+
return vertical || horizontal;
|
2942
|
+
};
|
2943
|
+
|
2944
|
+
var isScrollable = function ( $el ) {
|
2945
|
+
|
2946
|
+
var rez = false;
|
2947
|
+
|
2948
|
+
while ( true ) {
|
2949
|
+
rez = hasScrollbars( $el.get(0) );
|
2950
|
+
|
2951
|
+
if ( rez ) {
|
2952
|
+
break;
|
2953
|
+
}
|
2954
|
+
|
2955
|
+
$el = $el.parent();
|
2956
|
+
|
2957
|
+
if ( !$el.length || $el.hasClass('fancybox-slider') || $el.is('body') ) {
|
2958
|
+
break;
|
2959
|
+
}
|
2960
|
+
|
2961
|
+
}
|
2962
|
+
|
2963
|
+
return rez;
|
2964
|
+
|
2965
|
+
};
|
2966
|
+
|
2967
|
+
|
2968
|
+
var Guestures = function ( instance ) {
|
2969
|
+
|
2970
|
+
var self = this;
|
2971
|
+
|
2972
|
+
self.instance = instance;
|
2973
|
+
|
2974
|
+
self.$wrap = instance.$refs.slider_wrap;
|
2975
|
+
self.$slider = instance.$refs.slider;
|
2976
|
+
self.$container = instance.$refs.container;
|
2977
|
+
|
2978
|
+
self.destroy();
|
2979
|
+
|
2980
|
+
self.$wrap.on('touchstart.fb mousedown.fb', $.proxy(self, "ontouchstart"));
|
2981
|
+
|
2982
|
+
};
|
2983
|
+
|
2984
|
+
Guestures.prototype.destroy = function() {
|
2985
|
+
|
2986
|
+
this.$wrap.off('touchstart.fb mousedown.fb touchmove.fb mousemove.fb touchend.fb touchcancel.fb mouseup.fb mouseleave.fb');
|
2987
|
+
|
2988
|
+
};
|
2989
|
+
|
2990
|
+
Guestures.prototype.ontouchstart = function( e ) {
|
2991
|
+
|
2992
|
+
var self = this;
|
2993
|
+
|
2994
|
+
var $target = $( e.target );
|
2995
|
+
var instance = self.instance;
|
2996
|
+
var current = instance.current;
|
2997
|
+
var $content = current.$content || current.$placeholder;
|
2998
|
+
|
2999
|
+
self.startPoints = pointers( e );
|
3000
|
+
|
3001
|
+
self.$target = $target;
|
3002
|
+
self.$content = $content;
|
3003
|
+
|
3004
|
+
self.canvasWidth = Math.round( current.$slide[0].clientWidth );
|
3005
|
+
self.canvasHeight = Math.round( current.$slide[0].clientHeight );
|
3006
|
+
|
3007
|
+
self.startEvent = e;
|
3008
|
+
|
3009
|
+
// Skip if clicked on the scrollbar
|
3010
|
+
if ( e.originalEvent.clientX > self.canvasWidth + current.$slide.offset().left ) {
|
3011
|
+
return true;
|
3012
|
+
}
|
3013
|
+
|
3014
|
+
// Ignore taping on links, buttons and scrollable items
|
3015
|
+
if ( isClickable( $target ) || isClickable( $target.parent() ) || ( isScrollable( $target ) ) ) {
|
3016
|
+
return;
|
3017
|
+
}
|
3018
|
+
|
3019
|
+
// If "touch" is disabled, then handle click event
|
3020
|
+
if ( !current.opts.touch ) {
|
3021
|
+
self.endPoints = self.startPoints;
|
3022
|
+
|
3023
|
+
return self.ontap();
|
3024
|
+
}
|
3025
|
+
|
3026
|
+
// Ignore right click
|
3027
|
+
if ( e.originalEvent && e.originalEvent.button == 2 ) {
|
3028
|
+
return;
|
3029
|
+
}
|
3030
|
+
|
3031
|
+
e.stopPropagation();
|
3032
|
+
e.preventDefault();
|
3033
|
+
|
3034
|
+
if ( !current || self.instance.isAnimating || self.instance.isClosing ) {
|
3035
|
+
return;
|
3036
|
+
}
|
3037
|
+
|
3038
|
+
// Prevent zooming if already swiping
|
3039
|
+
if ( !self.startPoints || ( self.startPoints.length > 1 && !current.isMoved ) ) {
|
3040
|
+
return;
|
3041
|
+
}
|
3042
|
+
|
3043
|
+
self.$wrap.off('touchmove.fb mousemove.fb', $.proxy(self, "ontouchmove"));
|
3044
|
+
self.$wrap.off('touchend.fb touchcancel.fb mouseup.fb mouseleave.fb', $.proxy(self, "ontouchend"));
|
3045
|
+
|
3046
|
+
self.$wrap.on('touchend.fb touchcancel.fb mouseup.fb mouseleave.fb', $.proxy(self, "ontouchend"));
|
3047
|
+
self.$wrap.on('touchmove.fb mousemove.fb', $.proxy(self, "ontouchmove"));
|
3048
|
+
|
3049
|
+
self.startTime = new Date().getTime();
|
3050
|
+
self.distanceX = self.distanceY = self.distance = 0;
|
3051
|
+
|
3052
|
+
self.canTap = false;
|
3053
|
+
self.isPanning = false;
|
3054
|
+
self.isSwiping = false;
|
3055
|
+
self.isZooming = false;
|
3056
|
+
|
3057
|
+
self.sliderStartPos = $.fancybox.getTranslate( self.$slider );
|
3058
|
+
|
3059
|
+
self.contentStartPos = $.fancybox.getTranslate( self.$content );
|
3060
|
+
self.contentLastPos = null;
|
3061
|
+
|
3062
|
+
if ( self.startPoints.length === 1 && !self.isZooming ) {
|
3063
|
+
self.canTap = current.isMoved;
|
3064
|
+
|
3065
|
+
if ( current.type === 'image' && ( self.contentStartPos.width > self.canvasWidth + 1 || self.contentStartPos.height > self.canvasHeight + 1 ) ) {
|
3066
|
+
|
3067
|
+
$.fancybox.stop( self.$content );
|
3068
|
+
|
3069
|
+
self.isPanning = true;
|
3070
|
+
|
3071
|
+
} else {
|
3072
|
+
|
3073
|
+
$.fancybox.stop( self.$slider );
|
3074
|
+
|
3075
|
+
self.isSwiping = true;
|
3076
|
+
}
|
3077
|
+
|
3078
|
+
self.$container.addClass('fancybox-controls--isGrabbing');
|
3079
|
+
|
3080
|
+
}
|
3081
|
+
|
3082
|
+
if ( self.startPoints.length === 2 && current.isMoved && !current.hasError && current.type === 'image' && ( current.isLoaded || current.$ghost ) ) {
|
3083
|
+
|
3084
|
+
self.isZooming = true;
|
3085
|
+
|
3086
|
+
self.isSwiping = false;
|
3087
|
+
self.isPanning = false;
|
3088
|
+
|
3089
|
+
$.fancybox.stop( self.$content );
|
3090
|
+
|
3091
|
+
self.centerPointStartX = ( ( self.startPoints[0].x + self.startPoints[1].x ) * 0.5 ) - $(window).scrollLeft();
|
3092
|
+
self.centerPointStartY = ( ( self.startPoints[0].y + self.startPoints[1].y ) * 0.5 ) - $(window).scrollTop();
|
3093
|
+
|
3094
|
+
self.percentageOfImageAtPinchPointX = ( self.centerPointStartX - self.contentStartPos.left ) / self.contentStartPos.width;
|
3095
|
+
self.percentageOfImageAtPinchPointY = ( self.centerPointStartY - self.contentStartPos.top ) / self.contentStartPos.height;
|
3096
|
+
|
3097
|
+
self.startDistanceBetweenFingers = distance( self.startPoints[0], self.startPoints[1] );
|
3098
|
+
}
|
3099
|
+
|
3100
|
+
};
|
3101
|
+
|
3102
|
+
Guestures.prototype.ontouchmove = function( e ) {
|
3103
|
+
|
3104
|
+
var self = this;
|
3105
|
+
|
3106
|
+
e.preventDefault();
|
3107
|
+
|
3108
|
+
self.newPoints = pointers( e );
|
3109
|
+
|
3110
|
+
if ( !self.newPoints || !self.newPoints.length ) {
|
3111
|
+
return;
|
3112
|
+
}
|
3113
|
+
|
3114
|
+
self.distanceX = distance( self.newPoints[0], self.startPoints[0], 'x' );
|
3115
|
+
self.distanceY = distance( self.newPoints[0], self.startPoints[0], 'y' );
|
3116
|
+
|
3117
|
+
self.distance = distance( self.newPoints[0], self.startPoints[0] );
|
3118
|
+
|
3119
|
+
// Skip false ontouchmove events (Chrome)
|
3120
|
+
if ( self.distance > 0 ) {
|
3121
|
+
|
3122
|
+
if ( self.isSwiping ) {
|
3123
|
+
self.onSwipe();
|
3124
|
+
|
3125
|
+
} else if ( self.isPanning ) {
|
3126
|
+
self.onPan();
|
3127
|
+
|
3128
|
+
} else if ( self.isZooming ) {
|
3129
|
+
self.onZoom();
|
3130
|
+
}
|
3131
|
+
|
3132
|
+
}
|
3133
|
+
|
3134
|
+
};
|
3135
|
+
|
3136
|
+
Guestures.prototype.onSwipe = function() {
|
3137
|
+
|
3138
|
+
var self = this;
|
3139
|
+
|
3140
|
+
var swiping = self.isSwiping;
|
3141
|
+
var left = self.sliderStartPos.left;
|
3142
|
+
var angle;
|
3143
|
+
|
3144
|
+
if ( swiping === true ) {
|
3145
|
+
|
3146
|
+
if ( Math.abs( self.distance ) > 10 ) {
|
3147
|
+
|
3148
|
+
if ( self.instance.group.length < 2 ) {
|
3149
|
+
self.isSwiping = 'y';
|
3150
|
+
|
3151
|
+
} else if ( !self.instance.current.isMoved || self.instance.opts.touch.vertical === false || ( self.instance.opts.touch.vertical === 'auto' && $( window ).width() > 800 ) ) {
|
3152
|
+
self.isSwiping = 'x';
|
3153
|
+
|
3154
|
+
} else {
|
3155
|
+
angle = Math.abs( Math.atan2( self.distanceY, self.distanceX ) * 180 / Math.PI );
|
3156
|
+
|
3157
|
+
self.isSwiping = ( angle > 45 && angle < 135 ) ? 'y' : 'x';
|
3158
|
+
}
|
3159
|
+
|
3160
|
+
self.canTap = false;
|
3161
|
+
|
3162
|
+
self.instance.current.isMoved = false;
|
3163
|
+
|
3164
|
+
// Reset points to avoid jumping, because we dropped first swipes to calculate the angle
|
3165
|
+
self.startPoints = self.newPoints;
|
3166
|
+
}
|
3167
|
+
|
3168
|
+
} else {
|
3169
|
+
|
3170
|
+
if ( swiping == 'x' ) {
|
3171
|
+
|
3172
|
+
// Sticky edges
|
3173
|
+
if ( !self.instance.current.opts.loop && self.instance.current.index === 0 && self.distanceX > 0 ) {
|
3174
|
+
left = left + Math.pow( self.distanceX, 0.8 );
|
3175
|
+
|
3176
|
+
} else if ( !self.instance.current.opts.loop &&self.instance.current.index === self.instance.group.length - 1 && self.distanceX < 0 ) {
|
3177
|
+
left = left - Math.pow( -self.distanceX, 0.8 );
|
3178
|
+
|
3179
|
+
} else {
|
3180
|
+
left = left + self.distanceX;
|
3181
|
+
}
|
3182
|
+
|
3183
|
+
}
|
3184
|
+
|
3185
|
+
self.sliderLastPos = {
|
3186
|
+
top : swiping == 'x' ? 0 : self.sliderStartPos.top + self.distanceY,
|
3187
|
+
left : left
|
3188
|
+
};
|
3189
|
+
|
3190
|
+
requestAFrame(function() {
|
3191
|
+
$.fancybox.setTranslate( self.$slider, self.sliderLastPos );
|
3192
|
+
});
|
3193
|
+
}
|
3194
|
+
|
3195
|
+
};
|
3196
|
+
|
3197
|
+
Guestures.prototype.onPan = function() {
|
3198
|
+
|
3199
|
+
var self = this;
|
3200
|
+
|
3201
|
+
var newOffsetX, newOffsetY, newPos;
|
3202
|
+
|
3203
|
+
self.canTap = false;
|
3204
|
+
|
3205
|
+
if ( self.contentStartPos.width > self.canvasWidth ) {
|
3206
|
+
newOffsetX = self.contentStartPos.left + self.distanceX;
|
3207
|
+
|
3208
|
+
} else {
|
3209
|
+
newOffsetX = self.contentStartPos.left;
|
3210
|
+
}
|
3211
|
+
|
3212
|
+
newOffsetY = self.contentStartPos.top + self.distanceY;
|
3213
|
+
|
3214
|
+
newPos = self.limitMovement( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
|
3215
|
+
|
3216
|
+
newPos.scaleX = self.contentStartPos.scaleX;
|
3217
|
+
newPos.scaleY = self.contentStartPos.scaleY;
|
3218
|
+
|
3219
|
+
self.contentLastPos = newPos;
|
3220
|
+
|
3221
|
+
requestAFrame(function() {
|
3222
|
+
$.fancybox.setTranslate( self.$content, self.contentLastPos );
|
3223
|
+
});
|
3224
|
+
};
|
3225
|
+
|
3226
|
+
// Make panning sticky to the edges
|
3227
|
+
Guestures.prototype.limitMovement = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
|
3228
|
+
|
3229
|
+
var self = this;
|
3230
|
+
|
3231
|
+
var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY;
|
3232
|
+
|
3233
|
+
var canvasWidth = self.canvasWidth;
|
3234
|
+
var canvasHeight = self.canvasHeight;
|
3235
|
+
|
3236
|
+
var currentOffsetX = self.contentStartPos.left;
|
3237
|
+
var currentOffsetY = self.contentStartPos.top;
|
3238
|
+
|
3239
|
+
var distanceX = self.distanceX;
|
3240
|
+
var distanceY = self.distanceY;
|
3241
|
+
|
3242
|
+
// Slow down proportionally to traveled distance
|
3243
|
+
|
3244
|
+
minTranslateX = Math.max(0, canvasWidth * 0.5 - newWidth * 0.5 );
|
3245
|
+
minTranslateY = Math.max(0, canvasHeight * 0.5 - newHeight * 0.5 );
|
3246
|
+
|
3247
|
+
maxTranslateX = Math.min( canvasWidth - newWidth, canvasWidth * 0.5 - newWidth * 0.5 );
|
3248
|
+
maxTranslateY = Math.min( canvasHeight - newHeight, canvasHeight * 0.5 - newHeight * 0.5 );
|
3249
|
+
|
3250
|
+
if ( newWidth > canvasWidth ) {
|
3251
|
+
|
3252
|
+
// ->
|
3253
|
+
if ( distanceX > 0 && newOffsetX > minTranslateX ) {
|
3254
|
+
newOffsetX = minTranslateX - 1 + Math.pow( -minTranslateX + currentOffsetX + distanceX, 0.8 ) || 0;
|
3255
|
+
}
|
3256
|
+
|
3257
|
+
// <-
|
3258
|
+
if ( distanceX < 0 && newOffsetX < maxTranslateX ) {
|
3259
|
+
newOffsetX = maxTranslateX + 1 - Math.pow( maxTranslateX - currentOffsetX - distanceX, 0.8 ) || 0;
|
3260
|
+
}
|
3261
|
+
|
3262
|
+
}
|
3263
|
+
|
3264
|
+
if ( newHeight > canvasHeight ) {
|
3265
|
+
|
3266
|
+
// \/
|
3267
|
+
if ( distanceY > 0 && newOffsetY > minTranslateY ) {
|
3268
|
+
newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8 ) || 0;
|
3269
|
+
}
|
3270
|
+
|
3271
|
+
// /\
|
3272
|
+
if ( distanceY < 0 && newOffsetY < maxTranslateY ) {
|
3273
|
+
newOffsetY = maxTranslateY + 1 - Math.pow ( maxTranslateY - currentOffsetY - distanceY, 0.8 ) || 0;
|
3274
|
+
}
|
3275
|
+
|
3276
|
+
}
|
3277
|
+
|
3278
|
+
return {
|
3279
|
+
top : newOffsetY,
|
3280
|
+
left : newOffsetX
|
3281
|
+
};
|
3282
|
+
|
3283
|
+
};
|
3284
|
+
|
3285
|
+
|
3286
|
+
Guestures.prototype.limitPosition = function( newOffsetX, newOffsetY, newWidth, newHeight ) {
|
3287
|
+
|
3288
|
+
var self = this;
|
3289
|
+
|
3290
|
+
var canvasWidth = self.canvasWidth;
|
3291
|
+
var canvasHeight = self.canvasHeight;
|
3292
|
+
|
3293
|
+
if ( newWidth > canvasWidth ) {
|
3294
|
+
newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;
|
3295
|
+
newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;
|
3296
|
+
|
3297
|
+
} else {
|
3298
|
+
|
3299
|
+
// Center horizontally
|
3300
|
+
newOffsetX = Math.max( 0, canvasWidth / 2 - newWidth / 2 );
|
3301
|
+
|
3302
|
+
}
|
3303
|
+
|
3304
|
+
if ( newHeight > canvasHeight ) {
|
3305
|
+
newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;
|
3306
|
+
newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;
|
3307
|
+
|
3308
|
+
} else {
|
3309
|
+
|
3310
|
+
// Center vertically
|
3311
|
+
newOffsetY = Math.max( 0, canvasHeight / 2 - newHeight / 2 );
|
3312
|
+
|
3313
|
+
}
|
3314
|
+
|
3315
|
+
return {
|
3316
|
+
top : newOffsetY,
|
3317
|
+
left : newOffsetX
|
3318
|
+
};
|
3319
|
+
|
3320
|
+
};
|
3321
|
+
|
3322
|
+
Guestures.prototype.onZoom = function() {
|
3323
|
+
|
3324
|
+
var self = this;
|
3325
|
+
|
3326
|
+
// Calculate current distance between points to get pinch ratio and new width and height
|
3327
|
+
|
3328
|
+
var currentWidth = self.contentStartPos.width;
|
3329
|
+
var currentHeight = self.contentStartPos.height;
|
3330
|
+
|
3331
|
+
var currentOffsetX = self.contentStartPos.left;
|
3332
|
+
var currentOffsetY = self.contentStartPos.top;
|
3333
|
+
|
3334
|
+
var endDistanceBetweenFingers = distance( self.newPoints[0], self.newPoints[1] );
|
3335
|
+
|
3336
|
+
var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;
|
3337
|
+
|
3338
|
+
var newWidth = Math.floor( currentWidth * pinchRatio );
|
3339
|
+
var newHeight = Math.floor( currentHeight * pinchRatio );
|
3340
|
+
|
3341
|
+
// This is the translation due to pinch-zooming
|
3342
|
+
var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX;
|
3343
|
+
var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;
|
3344
|
+
|
3345
|
+
//Point between the two touches
|
3346
|
+
|
3347
|
+
var centerPointEndX = ((self.newPoints[0].x + self.newPoints[1].x) / 2) - $(window).scrollLeft();
|
3348
|
+
var centerPointEndY = ((self.newPoints[0].y + self.newPoints[1].y) / 2) - $(window).scrollTop();
|
3349
|
+
|
3350
|
+
// And this is the translation due to translation of the centerpoint
|
3351
|
+
// between the two fingers
|
3352
|
+
|
3353
|
+
var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;
|
3354
|
+
var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;
|
3355
|
+
|
3356
|
+
// The new offset is the old/current one plus the total translation
|
3357
|
+
|
3358
|
+
var newOffsetX = currentOffsetX + ( translateFromZoomingX + translateFromTranslatingX );
|
3359
|
+
var newOffsetY = currentOffsetY + ( translateFromZoomingY + translateFromTranslatingY );
|
3360
|
+
|
3361
|
+
var newPos = {
|
3362
|
+
top : newOffsetY,
|
3363
|
+
left : newOffsetX,
|
3364
|
+
scaleX : self.contentStartPos.scaleX * pinchRatio,
|
3365
|
+
scaleY : self.contentStartPos.scaleY * pinchRatio
|
3366
|
+
};
|
3367
|
+
|
3368
|
+
self.canTap = false;
|
3369
|
+
|
3370
|
+
self.newWidth = newWidth;
|
3371
|
+
self.newHeight = newHeight;
|
3372
|
+
|
3373
|
+
self.contentLastPos = newPos;
|
3374
|
+
|
3375
|
+
requestAFrame(function() {
|
3376
|
+
$.fancybox.setTranslate( self.$content, self.contentLastPos );
|
3377
|
+
});
|
3378
|
+
|
3379
|
+
};
|
3380
|
+
|
3381
|
+
Guestures.prototype.ontouchend = function( e ) {
|
3382
|
+
|
3383
|
+
var self = this;
|
3384
|
+
|
3385
|
+
var current = self.instance.current;
|
3386
|
+
|
3387
|
+
var dMs = Math.max( (new Date().getTime() ) - self.startTime, 1);
|
3388
|
+
|
3389
|
+
var swiping = self.isSwiping;
|
3390
|
+
var panning = self.isPanning;
|
3391
|
+
var zooming = self.isZooming;
|
3392
|
+
|
3393
|
+
self.endPoints = pointers( e );
|
3394
|
+
|
3395
|
+
self.$container.removeClass('fancybox-controls--isGrabbing');
|
3396
|
+
|
3397
|
+
self.$wrap.off('touchmove.fb mousemove.fb', $.proxy(this, "ontouchmove"));
|
3398
|
+
self.$wrap.off('touchend.fb touchcancel.fb mouseup.fb mouseleave.fb', $.proxy(this, "ontouchend"));
|
3399
|
+
|
3400
|
+
self.isSwiping = false;
|
3401
|
+
self.isPanning = false;
|
3402
|
+
self.isZooming = false;
|
3403
|
+
|
3404
|
+
if ( self.canTap ) {
|
3405
|
+
return self.ontap();
|
3406
|
+
}
|
3407
|
+
|
3408
|
+
// Speed in px/ms
|
3409
|
+
self.velocityX = self.distanceX / dMs * 0.5;
|
3410
|
+
self.velocityY = self.distanceY / dMs * 0.5;
|
3411
|
+
|
3412
|
+
self.speed = current.opts.speed || 330;
|
3413
|
+
|
3414
|
+
self.speedX = Math.max( self.speed * 0.75, Math.min( self.speed * 1.5, ( 1 / Math.abs( self.velocityX ) ) * self.speed ) );
|
3415
|
+
self.speedY = Math.max( self.speed * 0.75, Math.min( self.speed * 1.5, ( 1 / Math.abs( self.velocityY ) ) * self.speed ) );
|
3416
|
+
|
3417
|
+
if ( panning ) {
|
3418
|
+
self.endPanning();
|
3419
|
+
|
3420
|
+
} else if ( zooming ) {
|
3421
|
+
self.endZooming();
|
3422
|
+
|
3423
|
+
} else {
|
3424
|
+
self.endSwiping( swiping );
|
3425
|
+
}
|
3426
|
+
|
3427
|
+
return;
|
3428
|
+
};
|
3429
|
+
|
3430
|
+
Guestures.prototype.endSwiping = function( swiping ) {
|
3431
|
+
|
3432
|
+
var self = this;
|
3433
|
+
|
3434
|
+
// Close if swiped vertically / navigate if horizontally
|
3435
|
+
|
3436
|
+
if ( swiping == 'y' && Math.abs( self.distanceY ) > 50 ) {
|
3437
|
+
|
3438
|
+
// Continue vertical movement
|
3439
|
+
|
3440
|
+
$.fancybox.animate( self.$slider, null, {
|
3441
|
+
top : self.sliderStartPos.top + self.distanceY + self.velocityY * 150,
|
3442
|
+
left : self.sliderStartPos.left,
|
3443
|
+
opacity : 0
|
3444
|
+
}, self.speedY );
|
3445
|
+
|
3446
|
+
self.instance.close( true );
|
3447
|
+
|
3448
|
+
} else if ( swiping == 'x' && self.distanceX > 50 ) {
|
3449
|
+
self.instance.previous( self.speedX );
|
3450
|
+
|
3451
|
+
} else if ( swiping == 'x' && self.distanceX < -50 ) {
|
3452
|
+
self.instance.next( self.speedX );
|
3453
|
+
|
3454
|
+
} else {
|
3455
|
+
|
3456
|
+
// Move back to center
|
3457
|
+
self.instance.update( false, true, 150 );
|
3458
|
+
|
3459
|
+
}
|
3460
|
+
|
3461
|
+
};
|
3462
|
+
|
3463
|
+
Guestures.prototype.endPanning = function() {
|
3464
|
+
|
3465
|
+
var self = this;
|
3466
|
+
var newOffsetX, newOffsetY, newPos;
|
3467
|
+
|
3468
|
+
if ( !self.contentLastPos ) {
|
3469
|
+
return;
|
3470
|
+
}
|
3471
|
+
|
3472
|
+
newOffsetX = self.contentLastPos.left + ( self.velocityX * self.speed * 2 );
|
3473
|
+
newOffsetY = self.contentLastPos.top + ( self.velocityY * self.speed * 2 );
|
3474
|
+
|
3475
|
+
newPos = self.limitPosition( newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height );
|
3476
|
+
|
3477
|
+
newPos.width = self.contentStartPos.width;
|
3478
|
+
newPos.height = self.contentStartPos.height;
|
3479
|
+
|
3480
|
+
$.fancybox.animate( self.$content, null, newPos, self.speed, "easeOutSine" );
|
3481
|
+
|
3482
|
+
};
|
3483
|
+
|
3484
|
+
|
3485
|
+
Guestures.prototype.endZooming = function() {
|
3486
|
+
|
3487
|
+
var self = this;
|
3488
|
+
|
3489
|
+
var current = self.instance.current;
|
3490
|
+
|
3491
|
+
var newOffsetX, newOffsetY, newPos, reset;
|
3492
|
+
|
3493
|
+
var newWidth = self.newWidth;
|
3494
|
+
var newHeight = self.newHeight;
|
3495
|
+
|
3496
|
+
if ( !self.contentLastPos ) {
|
3497
|
+
return;
|
3498
|
+
}
|
3499
|
+
|
3500
|
+
newOffsetX = self.contentLastPos.left;
|
3501
|
+
newOffsetY = self.contentLastPos.top;
|
3502
|
+
|
3503
|
+
reset = {
|
3504
|
+
top : newOffsetY,
|
3505
|
+
left : newOffsetX,
|
3506
|
+
width : newWidth,
|
3507
|
+
height : newHeight,
|
3508
|
+
scaleX : 1,
|
3509
|
+
scaleY : 1
|
3510
|
+
};
|
3511
|
+
|
3512
|
+
// Reset scalex/scaleY values; this helps for perfomance and does not break animation
|
3513
|
+
$.fancybox.setTranslate( self.$content, reset );
|
3514
|
+
|
3515
|
+
if ( newWidth < self.canvasWidth && newHeight < self.canvasHeight ) {
|
3516
|
+
self.instance.scaleToFit( 150 );
|
3517
|
+
|
3518
|
+
} else if ( newWidth > current.width || newHeight > current.height ) {
|
3519
|
+
self.instance.scaleToActual( self.centerPointStartX, self.centerPointStartY, 150 );
|
3520
|
+
|
3521
|
+
} else {
|
3522
|
+
|
3523
|
+
newPos = self.limitPosition( newOffsetX, newOffsetY, newWidth, newHeight );
|
3524
|
+
|
3525
|
+
$.fancybox.animate( self.$content, null, newPos, self.speed, "easeOutSine" );
|
3526
|
+
|
3527
|
+
}
|
3528
|
+
|
3529
|
+
};
|
3530
|
+
|
3531
|
+
Guestures.prototype.ontap = function() {
|
3532
|
+
|
3533
|
+
var self = this;
|
3534
|
+
|
3535
|
+
var instance = self.instance;
|
3536
|
+
var current = instance.current;
|
3537
|
+
|
3538
|
+
var x = self.endPoints[0].x;
|
3539
|
+
var y = self.endPoints[0].y;
|
3540
|
+
|
3541
|
+
x = x - self.$wrap.offset().left;
|
3542
|
+
y = y - self.$wrap.offset().top;
|
3543
|
+
|
3544
|
+
// Stop slideshow
|
3545
|
+
if ( instance.SlideShow && instance.SlideShow.isActive ) {
|
3546
|
+
instance.SlideShow.stop();
|
3547
|
+
}
|
3548
|
+
|
3549
|
+
if ( !$.fancybox.isTouch ) {
|
3550
|
+
|
3551
|
+
if ( current.opts.closeClickOutside && self.$target.is('.fancybox-slide') ) {
|
3552
|
+
instance.close( self.startEvent );
|
3553
|
+
|
3554
|
+
return;
|
3555
|
+
}
|
3556
|
+
|
3557
|
+
if ( current.type == 'image' && current.isMoved ) {
|
3558
|
+
|
3559
|
+
if ( instance.canPan() ) {
|
3560
|
+
instance.scaleToFit();
|
3561
|
+
|
3562
|
+
} else if ( instance.isScaledDown() ) {
|
3563
|
+
instance.scaleToActual( x, y );
|
3564
|
+
|
3565
|
+
} else if ( instance.group.length < 2 ) {
|
3566
|
+
instance.close( self.startEvent );
|
3567
|
+
}
|
3568
|
+
|
3569
|
+
}
|
3570
|
+
|
3571
|
+
return;
|
3572
|
+
}
|
3573
|
+
|
3574
|
+
|
3575
|
+
// Double tap
|
3576
|
+
if ( self.tapped ) {
|
3577
|
+
|
3578
|
+
clearTimeout( self.tapped );
|
3579
|
+
|
3580
|
+
self.tapped = null;
|
3581
|
+
|
3582
|
+
if ( Math.abs( x - self.x ) > 50 || Math.abs( y - self.y ) > 50 || !current.isMoved ) {
|
3583
|
+
return this;
|
3584
|
+
}
|
3585
|
+
|
3586
|
+
if ( current.type == 'image' && ( current.isLoaded || current.$ghost ) ) {
|
3587
|
+
|
3588
|
+
if ( instance.canPan() ) {
|
3589
|
+
instance.scaleToFit();
|
3590
|
+
|
3591
|
+
} else if ( instance.isScaledDown() ) {
|
3592
|
+
instance.scaleToActual( x, y );
|
3593
|
+
|
3594
|
+
}
|
3595
|
+
|
3596
|
+
}
|
3597
|
+
|
3598
|
+
} else {
|
3599
|
+
|
3600
|
+
// Single tap
|
3601
|
+
|
3602
|
+
self.x = x;
|
3603
|
+
self.y = y;
|
3604
|
+
|
3605
|
+
self.tapped = setTimeout(function() {
|
3606
|
+
self.tapped = null;
|
3607
|
+
|
3608
|
+
instance.toggleControls( true );
|
3609
|
+
|
3610
|
+
}, 300);
|
3611
|
+
}
|
3612
|
+
|
3613
|
+
return this;
|
3614
|
+
};
|
3615
|
+
|
3616
|
+
$(document).on('onActivate.fb', function (e, instance) {
|
3617
|
+
|
3618
|
+
if ( instance && !instance.Guestures ) {
|
3619
|
+
instance.Guestures = new Guestures( instance );
|
3620
|
+
}
|
3621
|
+
|
3622
|
+
});
|
3623
|
+
|
3624
|
+
$(document).on('beforeClose.fb', function (e, instance) {
|
3625
|
+
|
3626
|
+
if ( instance && instance.Guestures ) {
|
3627
|
+
instance.Guestures.destroy();
|
3628
|
+
}
|
3629
|
+
|
3630
|
+
});
|
3631
|
+
|
3632
|
+
|
3633
|
+
}(window, document, window.jQuery));
|
3634
|
+
|
3635
|
+
// ==========================================================================
|
3636
|
+
//
|
3637
|
+
// SlideShow
|
3638
|
+
// Enables slideshow functionality
|
3639
|
+
//
|
3640
|
+
// Example of usage:
|
3641
|
+
// $.fancybox.getInstance().slideShow.start()
|
3642
|
+
//
|
3643
|
+
// ==========================================================================
|
3644
|
+
;(function (document, $) {
|
3645
|
+
'use strict';
|
3646
|
+
|
3647
|
+
var SlideShow = function( instance ) {
|
3648
|
+
|
3649
|
+
this.instance = instance;
|
3650
|
+
|
3651
|
+
this.init();
|
3652
|
+
|
3653
|
+
};
|
3654
|
+
|
3655
|
+
$.extend( SlideShow.prototype, {
|
3656
|
+
timer : null,
|
3657
|
+
isActive : false,
|
3658
|
+
$button : null,
|
3659
|
+
speed : 3000,
|
3660
|
+
|
3661
|
+
init : function() {
|
3662
|
+
var self = this;
|
3663
|
+
|
3664
|
+
self.$button = $('<button data-fancybox-play class="fancybox-button fancybox-button--play" title="Slideshow (P)"></button>')
|
3665
|
+
.appendTo( self.instance.$refs.buttons );
|
3666
|
+
|
3667
|
+
self.instance.$refs.container.on('click', '[data-fancybox-play]', function() {
|
3668
|
+
self.toggle();
|
3669
|
+
});
|
3670
|
+
|
3671
|
+
},
|
3672
|
+
|
3673
|
+
set : function() {
|
3674
|
+
var self = this;
|
3675
|
+
|
3676
|
+
// Check if reached last element
|
3677
|
+
if ( self.instance && self.instance.current && (self.instance.current.opts.loop || self.instance.currIndex < self.instance.group.length - 1 )) {
|
3678
|
+
|
3679
|
+
self.timer = setTimeout(function() {
|
3680
|
+
self.instance.next();
|
3681
|
+
|
3682
|
+
}, self.instance.current.opts.slideShow.speed || self.speed);
|
3683
|
+
|
3684
|
+
} else {
|
3685
|
+
self.stop();
|
3686
|
+
}
|
3687
|
+
},
|
3688
|
+
|
3689
|
+
clear : function() {
|
3690
|
+
var self = this;
|
3691
|
+
|
3692
|
+
clearTimeout( self.timer );
|
3693
|
+
|
3694
|
+
self.timer = null;
|
3695
|
+
},
|
3696
|
+
|
3697
|
+
start : function() {
|
3698
|
+
var self = this;
|
3699
|
+
|
3700
|
+
self.stop();
|
3701
|
+
|
3702
|
+
if ( self.instance && self.instance.current && ( self.instance.current.opts.loop || self.instance.currIndex < self.instance.group.length - 1 )) {
|
3703
|
+
|
3704
|
+
self.instance.$refs.container.on({
|
3705
|
+
'beforeLoad.fb.player' : $.proxy(self, "clear"),
|
3706
|
+
'onComplete.fb.player' : $.proxy(self, "set"),
|
3707
|
+
});
|
3708
|
+
|
3709
|
+
self.isActive = true;
|
3710
|
+
|
3711
|
+
if ( self.instance.current.isComplete ) {
|
3712
|
+
self.set();
|
3713
|
+
}
|
3714
|
+
|
3715
|
+
self.instance.$refs.container.trigger('onPlayStart');
|
3716
|
+
|
3717
|
+
self.$button.addClass('fancybox-button--pause');
|
3718
|
+
}
|
3719
|
+
|
3720
|
+
},
|
3721
|
+
|
3722
|
+
stop: function() {
|
3723
|
+
var self = this;
|
3724
|
+
|
3725
|
+
self.clear();
|
3726
|
+
|
3727
|
+
self.instance.$refs.container
|
3728
|
+
.trigger('onPlayEnd')
|
3729
|
+
.off('.player');
|
3730
|
+
|
3731
|
+
self.$button.removeClass('fancybox-button--pause');
|
3732
|
+
|
3733
|
+
self.isActive = false;
|
3734
|
+
},
|
3735
|
+
|
3736
|
+
toggle : function() {
|
3737
|
+
var self = this;
|
3738
|
+
|
3739
|
+
if ( self.isActive ) {
|
3740
|
+
self.stop();
|
3741
|
+
|
3742
|
+
} else {
|
3743
|
+
self.start();
|
3744
|
+
}
|
3745
|
+
}
|
3746
|
+
|
3747
|
+
});
|
3748
|
+
|
3749
|
+
$(document).on('onInit.fb', function(e, instance) {
|
3750
|
+
|
3751
|
+
if ( instance && instance.group.length > 1 && !!instance.opts.slideShow && !instance.SlideShow ) {
|
3752
|
+
instance.SlideShow = new SlideShow( instance );
|
3753
|
+
}
|
3754
|
+
|
3755
|
+
});
|
3756
|
+
|
3757
|
+
$(document).on('beforeClose.fb onDeactivate.fb', function(e, instance) {
|
3758
|
+
|
3759
|
+
if ( instance && instance.SlideShow ) {
|
3760
|
+
instance.SlideShow.stop();
|
3761
|
+
}
|
3762
|
+
|
3763
|
+
});
|
3764
|
+
|
3765
|
+
}(document, window.jQuery));
|
3766
|
+
|
3767
|
+
// ==========================================================================
|
3768
|
+
//
|
3769
|
+
// FullScreen
|
3770
|
+
// Adds fullscreen functionality
|
3771
|
+
//
|
3772
|
+
// ==========================================================================
|
3773
|
+
;(function (document, $) {
|
3774
|
+
'use strict';
|
3775
|
+
|
3776
|
+
// Collection of methods supported by user browser
|
3777
|
+
var fn = (function () {
|
3778
|
+
|
3779
|
+
var fnMap = [
|
3780
|
+
[
|
3781
|
+
'requestFullscreen',
|
3782
|
+
'exitFullscreen',
|
3783
|
+
'fullscreenElement',
|
3784
|
+
'fullscreenEnabled',
|
3785
|
+
'fullscreenchange',
|
3786
|
+
'fullscreenerror'
|
3787
|
+
],
|
3788
|
+
// new WebKit
|
3789
|
+
[
|
3790
|
+
'webkitRequestFullscreen',
|
3791
|
+
'webkitExitFullscreen',
|
3792
|
+
'webkitFullscreenElement',
|
3793
|
+
'webkitFullscreenEnabled',
|
3794
|
+
'webkitfullscreenchange',
|
3795
|
+
'webkitfullscreenerror'
|
3796
|
+
|
3797
|
+
],
|
3798
|
+
// old WebKit (Safari 5.1)
|
3799
|
+
[
|
3800
|
+
'webkitRequestFullScreen',
|
3801
|
+
'webkitCancelFullScreen',
|
3802
|
+
'webkitCurrentFullScreenElement',
|
3803
|
+
'webkitCancelFullScreen',
|
3804
|
+
'webkitfullscreenchange',
|
3805
|
+
'webkitfullscreenerror'
|
3806
|
+
|
3807
|
+
],
|
3808
|
+
[
|
3809
|
+
'mozRequestFullScreen',
|
3810
|
+
'mozCancelFullScreen',
|
3811
|
+
'mozFullScreenElement',
|
3812
|
+
'mozFullScreenEnabled',
|
3813
|
+
'mozfullscreenchange',
|
3814
|
+
'mozfullscreenerror'
|
3815
|
+
],
|
3816
|
+
[
|
3817
|
+
'msRequestFullscreen',
|
3818
|
+
'msExitFullscreen',
|
3819
|
+
'msFullscreenElement',
|
3820
|
+
'msFullscreenEnabled',
|
3821
|
+
'MSFullscreenChange',
|
3822
|
+
'MSFullscreenError'
|
3823
|
+
]
|
3824
|
+
];
|
3825
|
+
|
3826
|
+
var val;
|
3827
|
+
var ret = {};
|
3828
|
+
var i, j;
|
3829
|
+
|
3830
|
+
for ( i = 0; i < fnMap.length; i++ ) {
|
3831
|
+
val = fnMap[ i ];
|
3832
|
+
|
3833
|
+
if ( val && val[ 1 ] in document ) {
|
3834
|
+
for ( j = 0; j < val.length; j++ ) {
|
3835
|
+
ret[ fnMap[ 0 ][ j ] ] = val[ j ];
|
3836
|
+
}
|
3837
|
+
|
3838
|
+
return ret;
|
3839
|
+
}
|
3840
|
+
}
|
3841
|
+
|
3842
|
+
return false;
|
3843
|
+
})();
|
3844
|
+
|
3845
|
+
if ( !fn ) {
|
3846
|
+
return;
|
3847
|
+
}
|
3848
|
+
|
3849
|
+
var FullScreen = {
|
3850
|
+
request : function ( elem ) {
|
3851
|
+
|
3852
|
+
elem = elem || document.documentElement;
|
3853
|
+
|
3854
|
+
elem[ fn.requestFullscreen ]( elem.ALLOW_KEYBOARD_INPUT );
|
3855
|
+
|
3856
|
+
},
|
3857
|
+
exit : function () {
|
3858
|
+
document[ fn.exitFullscreen ]();
|
3859
|
+
},
|
3860
|
+
toggle : function ( elem ) {
|
3861
|
+
|
3862
|
+
if ( this.isFullscreen() ) {
|
3863
|
+
this.exit();
|
3864
|
+
} else {
|
3865
|
+
this.request( elem );
|
3866
|
+
}
|
3867
|
+
|
3868
|
+
},
|
3869
|
+
isFullscreen : function() {
|
3870
|
+
return Boolean( document[ fn.fullscreenElement ] );
|
3871
|
+
},
|
3872
|
+
enabled : function() {
|
3873
|
+
return Boolean( document[ fn.fullscreenEnabled ] );
|
3874
|
+
}
|
3875
|
+
};
|
3876
|
+
|
3877
|
+
$(document).on({
|
3878
|
+
'onInit.fb' : function(e, instance) {
|
3879
|
+
var $container;
|
3880
|
+
|
3881
|
+
if ( instance && !!instance.opts.fullScreen && !instance.FullScreen) {
|
3882
|
+
$container = instance.$refs.container;
|
3883
|
+
|
3884
|
+
instance.$refs.button_fs = $('<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fullscreen" title="Full screen (F)"></button>')
|
3885
|
+
.appendTo( instance.$refs.buttons );
|
3886
|
+
|
3887
|
+
$container.on('click.fb-fullscreen', '[data-fancybox-fullscreen]', function(e) {
|
3888
|
+
|
3889
|
+
e.stopPropagation();
|
3890
|
+
e.preventDefault();
|
3891
|
+
|
3892
|
+
FullScreen.toggle( $container[ 0 ] );
|
3893
|
+
|
3894
|
+
});
|
3895
|
+
|
3896
|
+
if ( instance.opts.fullScreen.requestOnStart === true ) {
|
3897
|
+
FullScreen.request( $container[ 0 ] );
|
3898
|
+
}
|
3899
|
+
|
3900
|
+
}
|
3901
|
+
|
3902
|
+
}, 'beforeMove.fb' : function(e, instance) {
|
3903
|
+
|
3904
|
+
if ( instance && instance.$refs.button_fs ) {
|
3905
|
+
instance.$refs.button_fs.toggle( !!instance.current.opts.fullScreen );
|
3906
|
+
}
|
3907
|
+
|
3908
|
+
}, 'beforeClose.fb': function() {
|
3909
|
+
FullScreen.exit();
|
3910
|
+
}
|
3911
|
+
});
|
3912
|
+
|
3913
|
+
$(document).on(fn.fullscreenchange, function() {
|
3914
|
+
var instance = $.fancybox.getInstance();
|
3915
|
+
var $what = instance ? instance.current.$placeholder : null;
|
3916
|
+
|
3917
|
+
if ( $what ) {
|
3918
|
+
|
3919
|
+
// If image is zooming, then this will force it to stop and reposition properly
|
3920
|
+
$what.css( 'transition', 'none' );
|
3921
|
+
|
3922
|
+
instance.isAnimating = false;
|
3923
|
+
|
3924
|
+
instance.update( true, true, 0 );
|
3925
|
+
}
|
3926
|
+
|
3927
|
+
});
|
3928
|
+
|
3929
|
+
}(document, window.jQuery));
|
3930
|
+
|
3931
|
+
// ==========================================================================
|
3932
|
+
//
|
3933
|
+
// Thumbs
|
3934
|
+
// Displays thumbnails in a grid
|
3935
|
+
//
|
3936
|
+
// ==========================================================================
|
3937
|
+
;(function (document, $) {
|
3938
|
+
'use strict';
|
3939
|
+
|
3940
|
+
var FancyThumbs = function( instance ) {
|
3941
|
+
|
3942
|
+
this.instance = instance;
|
3943
|
+
|
3944
|
+
this.init();
|
3945
|
+
|
3946
|
+
};
|
3947
|
+
|
3948
|
+
$.extend( FancyThumbs.prototype, {
|
3949
|
+
|
3950
|
+
$button : null,
|
3951
|
+
$grid : null,
|
3952
|
+
$list : null,
|
3953
|
+
isVisible : false,
|
3954
|
+
|
3955
|
+
init : function() {
|
3956
|
+
var self = this;
|
3957
|
+
|
3958
|
+
self.$button = $('<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="Thumbnails (G)"></button>')
|
3959
|
+
.appendTo( this.instance.$refs.buttons )
|
3960
|
+
.on('touchend click', function(e) {
|
3961
|
+
e.stopPropagation();
|
3962
|
+
e.preventDefault();
|
3963
|
+
|
3964
|
+
self.toggle();
|
3965
|
+
});
|
3966
|
+
|
3967
|
+
},
|
3968
|
+
|
3969
|
+
create : function() {
|
3970
|
+
var instance = this.instance,
|
3971
|
+
list,
|
3972
|
+
src;
|
3973
|
+
|
3974
|
+
this.$grid = $('<div class="fancybox-thumbs"></div>').appendTo( instance.$refs.container );
|
3975
|
+
|
3976
|
+
list = '<ul>';
|
3977
|
+
|
3978
|
+
$.each(instance.group, function( i, item ) {
|
3979
|
+
|
3980
|
+
src = item.opts.thumb || ( item.opts.$thumb ? item.opts.$thumb.attr('src') : null );
|
3981
|
+
|
3982
|
+
if ( !src && item.type === 'image' ) {
|
3983
|
+
src = item.src;
|
3984
|
+
}
|
3985
|
+
|
3986
|
+
if ( src && src.length ) {
|
3987
|
+
list += '<li data-index="' + i + '" tabindex="0" class="fancybox-thumbs-loading"><img data-src="' + src + '" /></li>';
|
3988
|
+
}
|
3989
|
+
|
3990
|
+
});
|
3991
|
+
|
3992
|
+
list += '</ul>';
|
3993
|
+
|
3994
|
+
this.$list = $( list ).appendTo( this.$grid ).on('click touchstart', 'li', function() {
|
3995
|
+
|
3996
|
+
instance.jumpTo( $(this).data('index') );
|
3997
|
+
|
3998
|
+
});
|
3999
|
+
|
4000
|
+
this.$list.find('img').hide().one('load', function() {
|
4001
|
+
|
4002
|
+
var $parent = $(this).parent().removeClass('fancybox-thumbs-loading'),
|
4003
|
+
thumbWidth = $parent.outerWidth(),
|
4004
|
+
thumbHeight = $parent.outerHeight(),
|
4005
|
+
width,
|
4006
|
+
height,
|
4007
|
+
widthRatio,
|
4008
|
+
heightRatio;
|
4009
|
+
|
4010
|
+
width = this.naturalWidth || this.width;
|
4011
|
+
height = this.naturalHeight || this.height;
|
4012
|
+
|
4013
|
+
//Calculate thumbnail width/height and center it
|
4014
|
+
|
4015
|
+
widthRatio = width / thumbWidth;
|
4016
|
+
heightRatio = height / thumbHeight;
|
4017
|
+
|
4018
|
+
if (widthRatio >= 1 && heightRatio >= 1) {
|
4019
|
+
if (widthRatio > heightRatio) {
|
4020
|
+
width = width / heightRatio;
|
4021
|
+
height = thumbHeight;
|
4022
|
+
|
4023
|
+
} else {
|
4024
|
+
width = thumbWidth;
|
4025
|
+
height = height / widthRatio;
|
4026
|
+
}
|
4027
|
+
}
|
4028
|
+
|
4029
|
+
$(this).css({
|
4030
|
+
width : Math.floor(width),
|
4031
|
+
height : Math.floor(height),
|
4032
|
+
'margin-top' : Math.min( 0, Math.floor(thumbHeight * 0.3 - height * 0.3 ) ),
|
4033
|
+
'margin-left' : Math.min( 0, Math.floor(thumbWidth * 0.5 - width * 0.5 ) )
|
4034
|
+
}).show();
|
4035
|
+
|
4036
|
+
})
|
4037
|
+
.each(function() {
|
4038
|
+
this.src = $( this ).data( 'src' );
|
4039
|
+
});
|
4040
|
+
|
4041
|
+
},
|
4042
|
+
|
4043
|
+
focus : function() {
|
4044
|
+
|
4045
|
+
if ( this.instance.current ) {
|
4046
|
+
this.$list
|
4047
|
+
.children()
|
4048
|
+
.removeClass('fancybox-thumbs-active')
|
4049
|
+
.filter('[data-index="' + this.instance.current.index + '"]')
|
4050
|
+
.addClass('fancybox-thumbs-active')
|
4051
|
+
.focus();
|
4052
|
+
}
|
4053
|
+
|
4054
|
+
},
|
4055
|
+
|
4056
|
+
close : function() {
|
4057
|
+
|
4058
|
+
this.$grid.hide();
|
4059
|
+
|
4060
|
+
},
|
4061
|
+
|
4062
|
+
update : function() {
|
4063
|
+
|
4064
|
+
this.instance.$refs.container.toggleClass('fancybox-container--thumbs', this.isVisible);
|
4065
|
+
|
4066
|
+
if ( this.isVisible ) {
|
4067
|
+
|
4068
|
+
if ( !this.$grid ) {
|
4069
|
+
this.create();
|
4070
|
+
}
|
4071
|
+
|
4072
|
+
this.$grid.show();
|
4073
|
+
|
4074
|
+
this.focus();
|
4075
|
+
|
4076
|
+
} else if ( this.$grid ) {
|
4077
|
+
this.$grid.hide();
|
4078
|
+
}
|
4079
|
+
|
4080
|
+
this.instance.update();
|
4081
|
+
|
4082
|
+
},
|
4083
|
+
|
4084
|
+
hide : function() {
|
4085
|
+
|
4086
|
+
this.isVisible = false;
|
4087
|
+
|
4088
|
+
this.update();
|
4089
|
+
|
4090
|
+
},
|
4091
|
+
|
4092
|
+
show : function() {
|
4093
|
+
|
4094
|
+
this.isVisible = true;
|
4095
|
+
|
4096
|
+
this.update();
|
4097
|
+
|
4098
|
+
},
|
4099
|
+
|
4100
|
+
toggle : function() {
|
4101
|
+
|
4102
|
+
if ( this.isVisible ) {
|
4103
|
+
this.hide();
|
4104
|
+
|
4105
|
+
} else {
|
4106
|
+
this.show();
|
4107
|
+
}
|
4108
|
+
}
|
4109
|
+
|
4110
|
+
});
|
4111
|
+
|
4112
|
+
$(document).on('onInit.fb', function(e, instance) {
|
4113
|
+
var first = instance.group[0],
|
4114
|
+
second = instance.group[1];
|
4115
|
+
|
4116
|
+
if ( !!instance.opts.thumbs && !instance.Thumbs && instance.group.length > 1 && (
|
4117
|
+
( first.type == 'image' || first.opts.thumb || first.opts.$thumb ) &&
|
4118
|
+
( second.type == 'image' || second.opts.thumb || second.opts.$thumb )
|
4119
|
+
)
|
4120
|
+
) {
|
4121
|
+
|
4122
|
+
instance.Thumbs = new FancyThumbs( instance );
|
4123
|
+
}
|
4124
|
+
|
4125
|
+
});
|
4126
|
+
|
4127
|
+
$(document).on('beforeMove.fb', function(e, instance, item) {
|
4128
|
+
var self = instance && instance.Thumbs;
|
4129
|
+
|
4130
|
+
if ( !self ) {
|
4131
|
+
return;
|
4132
|
+
}
|
4133
|
+
|
4134
|
+
if ( item.modal ) {
|
4135
|
+
|
4136
|
+
self.$button.hide();
|
4137
|
+
|
4138
|
+
self.hide();
|
4139
|
+
|
4140
|
+
} else {
|
4141
|
+
|
4142
|
+
if ( instance.opts.thumbs.showOnStart === true && instance.firstRun ) {
|
4143
|
+
self.show();
|
4144
|
+
|
4145
|
+
}
|
4146
|
+
|
4147
|
+
self.$button.show();
|
4148
|
+
|
4149
|
+
if ( self.isVisible ) {
|
4150
|
+
self.focus();
|
4151
|
+
}
|
4152
|
+
|
4153
|
+
}
|
4154
|
+
|
4155
|
+
});
|
4156
|
+
|
4157
|
+
$(document).on('beforeClose.fb', function(e, instance) {
|
4158
|
+
|
4159
|
+
if ( instance && instance.Thumbs) {
|
4160
|
+
if ( instance.Thumbs.isVisible && instance.opts.thumbs.hideOnClosing !== false ) {
|
4161
|
+
instance.Thumbs.close();
|
4162
|
+
}
|
4163
|
+
|
4164
|
+
instance.Thumbs = null;
|
4165
|
+
}
|
4166
|
+
|
4167
|
+
});
|
4168
|
+
|
4169
|
+
}(document, window.jQuery));
|
4170
|
+
|
4171
|
+
// ==========================================================================
|
4172
|
+
//
|
4173
|
+
// Hash
|
4174
|
+
// Enables linking to each modal
|
4175
|
+
//
|
4176
|
+
// ==========================================================================
|
4177
|
+
;(function (document, window, $) {
|
4178
|
+
'use strict';
|
4179
|
+
|
4180
|
+
// Simple $.escapeSelector polyfill (for jQuery prior v3)
|
4181
|
+
if ( !$.escapeSelector ) {
|
4182
|
+
$.escapeSelector = function( sel ) {
|
4183
|
+
var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
|
4184
|
+
var fcssescape = function( ch, asCodePoint ) {
|
4185
|
+
if ( asCodePoint ) {
|
4186
|
+
// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
|
4187
|
+
if ( ch === "\0" ) {
|
4188
|
+
return "\uFFFD";
|
4189
|
+
}
|
4190
|
+
|
4191
|
+
// Control characters and (dependent upon position) numbers get escaped as code points
|
4192
|
+
return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
|
4193
|
+
}
|
4194
|
+
|
4195
|
+
// Other potentially-special ASCII characters get backslash-escaped
|
4196
|
+
return "\\" + ch;
|
4197
|
+
};
|
4198
|
+
|
4199
|
+
return ( sel + "" ).replace( rcssescape, fcssescape );
|
4200
|
+
};
|
4201
|
+
}
|
4202
|
+
|
4203
|
+
// Variable containing last hash value set by fancyBox
|
4204
|
+
// It will be used to determine if fancyBox needs to close after hash change is detected
|
4205
|
+
var currentHash = null;
|
4206
|
+
|
4207
|
+
// Get info about gallery name and current index from url
|
4208
|
+
function parseUrl() {
|
4209
|
+
var hash = window.location.hash.substr( 1 );
|
4210
|
+
var rez = hash.split( '-' );
|
4211
|
+
var index = rez.length > 1 && /^\+?\d+$/.test( rez[ rez.length - 1 ] ) ? parseInt( rez.pop( -1 ), 10 ) || 1 : 1;
|
4212
|
+
var gallery = rez.join( '-' );
|
4213
|
+
|
4214
|
+
// Index is starting from 1
|
4215
|
+
if ( index < 1 ) {
|
4216
|
+
index = 1;
|
4217
|
+
}
|
4218
|
+
|
4219
|
+
return {
|
4220
|
+
hash : hash,
|
4221
|
+
index : index,
|
4222
|
+
gallery : gallery
|
4223
|
+
};
|
4224
|
+
}
|
4225
|
+
|
4226
|
+
// Trigger click evnt on links to open new fancyBox instance
|
4227
|
+
function triggerFromUrl( url ) {
|
4228
|
+
var $el;
|
4229
|
+
|
4230
|
+
if ( url.gallery !== '' ) {
|
4231
|
+
|
4232
|
+
// If we can find element matching 'data-fancybox' atribute, then trigger click event for that ..
|
4233
|
+
$el = $( "[data-fancybox='" + $.escapeSelector( url.gallery ) + "']" ).eq( url.index - 1 );
|
4234
|
+
|
4235
|
+
if ( $el.length ) {
|
4236
|
+
$el.trigger( 'click' );
|
4237
|
+
|
4238
|
+
} else {
|
4239
|
+
|
4240
|
+
// .. if not, try finding element by ID
|
4241
|
+
$( "#" + $.escapeSelector( url.gallery ) + "" ).trigger( 'click' );
|
4242
|
+
|
4243
|
+
}
|
4244
|
+
|
4245
|
+
}
|
4246
|
+
}
|
4247
|
+
|
4248
|
+
// Get gallery name from current instance
|
4249
|
+
function getGallery( instance ) {
|
4250
|
+
var opts;
|
4251
|
+
|
4252
|
+
if ( !instance ) {
|
4253
|
+
return false;
|
4254
|
+
}
|
4255
|
+
|
4256
|
+
opts = instance.current ? instance.current.opts : instance.opts;
|
4257
|
+
|
4258
|
+
return opts.$orig ? opts.$orig.data( 'fancybox' ) : ( opts.hash || '' );
|
4259
|
+
}
|
4260
|
+
|
4261
|
+
// Star when DOM becomes ready
|
4262
|
+
$(function() {
|
4263
|
+
|
4264
|
+
// Small delay is used to allow other scripts to process "dom ready" event
|
4265
|
+
setTimeout(function() {
|
4266
|
+
|
4267
|
+
// Check if this module is not disabled
|
4268
|
+
if ( $.fancybox.defaults.hash === false ) {
|
4269
|
+
return;
|
4270
|
+
}
|
4271
|
+
|
4272
|
+
// Check if need to close after url has changed
|
4273
|
+
$(window).on('hashchange.fb', function() {
|
4274
|
+
var url = parseUrl();
|
4275
|
+
|
4276
|
+
if ( $.fancybox.getInstance() ) {
|
4277
|
+
if ( currentHash && currentHash !== url.gallery + '-' + url.index ) {
|
4278
|
+
currentHash = null;
|
4279
|
+
|
4280
|
+
$.fancybox.close();
|
4281
|
+
}
|
4282
|
+
|
4283
|
+
} else if ( url.gallery !== '' ) {
|
4284
|
+
triggerFromUrl( url );
|
4285
|
+
}
|
4286
|
+
|
4287
|
+
});
|
4288
|
+
|
4289
|
+
// Update hash when opening/closing fancyBox
|
4290
|
+
$(document).on({
|
4291
|
+
'onInit.fb' : function( e, instance ) {
|
4292
|
+
var url = parseUrl();
|
4293
|
+
var gallery = getGallery( instance );
|
4294
|
+
|
4295
|
+
// Make sure gallery start index matches index from hash
|
4296
|
+
if ( gallery && url.gallery && gallery == url.gallery ) {
|
4297
|
+
instance.currIndex = url.index - 1;
|
4298
|
+
}
|
4299
|
+
|
4300
|
+
}, 'beforeMove.fb' : function( e, instance, current ) {
|
4301
|
+
var gallery = getGallery( instance );
|
4302
|
+
|
4303
|
+
// Update window hash
|
4304
|
+
if ( gallery && gallery !== '' ) {
|
4305
|
+
|
4306
|
+
if ( window.location.hash.indexOf( gallery ) < 0 ) {
|
4307
|
+
instance.opts.origHash = window.location.hash;
|
4308
|
+
}
|
4309
|
+
|
4310
|
+
currentHash = gallery + ( instance.group.length > 1 ? '-' + ( current.index + 1 ) : '' );
|
4311
|
+
|
4312
|
+
if ( "pushState" in history ) {
|
4313
|
+
history.pushState( '', document.title, window.location.pathname + window.location.search + '#' + currentHash );
|
4314
|
+
|
4315
|
+
} else {
|
4316
|
+
window.location.hash = currentHash;
|
4317
|
+
}
|
4318
|
+
|
4319
|
+
}
|
4320
|
+
|
4321
|
+
}, 'beforeClose.fb' : function( e, instance, current ) {
|
4322
|
+
var gallery = getGallery( instance );
|
4323
|
+
var origHash = instance && instance.opts.origHash ? instance.opts.origHash : '';
|
4324
|
+
|
4325
|
+
// Remove hash from location bar
|
4326
|
+
if ( gallery && gallery !== '' ) {
|
4327
|
+
if ( "pushState" in history ) {
|
4328
|
+
history.pushState( '', document.title, window.location.pathname + window.location.search + origHash );
|
4329
|
+
|
4330
|
+
} else {
|
4331
|
+
window.location.hash = origHash;
|
4332
|
+
}
|
4333
|
+
}
|
4334
|
+
|
4335
|
+
currentHash = null;
|
4336
|
+
}
|
4337
|
+
});
|
4338
|
+
|
4339
|
+
// Check current hash and trigger click event on matching element to start fancyBox, if needed
|
4340
|
+
triggerFromUrl( parseUrl() );
|
4341
|
+
|
4342
|
+
}, 50);
|
4343
|
+
});
|
4344
|
+
|
4345
|
+
|
4346
|
+
}(document, window, window.jQuery));
|