promethee 1.7.12 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/promethee/rails/version.rb +1 -1
  3. data/node_modules/@fancyapps/fancybox/README.md +1 -1
  4. data/node_modules/@fancyapps/fancybox/dist/jquery.fancybox.css +162 -161
  5. data/node_modules/@fancyapps/fancybox/dist/jquery.fancybox.js +1281 -790
  6. data/node_modules/@fancyapps/fancybox/dist/jquery.fancybox.min.css +1 -1
  7. data/node_modules/@fancyapps/fancybox/dist/jquery.fancybox.min.js +4 -3
  8. data/node_modules/@fancyapps/fancybox/docs/index.html +1398 -1321
  9. data/node_modules/@fancyapps/fancybox/package.json +52 -43
  10. data/node_modules/@fancyapps/fancybox/src/css/core.css +144 -142
  11. data/node_modules/@fancyapps/fancybox/src/css/thumbs.css +20 -23
  12. data/node_modules/@fancyapps/fancybox/src/js/core.js +883 -536
  13. data/node_modules/@fancyapps/fancybox/src/js/fullscreen.js +67 -64
  14. data/node_modules/@fancyapps/fancybox/src/js/guestures.js +114 -78
  15. data/node_modules/@fancyapps/fancybox/src/js/hash.js +13 -18
  16. data/node_modules/@fancyapps/fancybox/src/js/media.js +118 -29
  17. data/node_modules/@fancyapps/fancybox/src/js/share.js +8 -6
  18. data/node_modules/@fancyapps/fancybox/src/js/slideshow.js +55 -32
  19. data/node_modules/@fancyapps/fancybox/src/js/thumbs.js +22 -26
  20. data/node_modules/@fancyapps/fancybox/src/js/wheel.js +1 -1
  21. metadata +2 -46
  22. data/node_modules/fancybox/CHANGELOG.md +0 -125
  23. data/node_modules/fancybox/README.md +0 -249
  24. data/node_modules/fancybox/bower.json +0 -24
  25. data/node_modules/fancybox/demo/1_b.jpg +0 -0
  26. data/node_modules/fancybox/demo/1_s.jpg +0 -0
  27. data/node_modules/fancybox/demo/2_b.jpg +0 -0
  28. data/node_modules/fancybox/demo/2_s.jpg +0 -0
  29. data/node_modules/fancybox/demo/3_b.jpg +0 -0
  30. data/node_modules/fancybox/demo/3_s.jpg +0 -0
  31. data/node_modules/fancybox/demo/4_b.jpg +0 -0
  32. data/node_modules/fancybox/demo/4_s.jpg +0 -0
  33. data/node_modules/fancybox/demo/5_b.jpg +0 -0
  34. data/node_modules/fancybox/demo/5_s.jpg +0 -0
  35. data/node_modules/fancybox/demo/ajax.txt +0 -15
  36. data/node_modules/fancybox/demo/iframe.html +0 -26
  37. data/node_modules/fancybox/demo/index.html +0 -312
  38. data/node_modules/fancybox/dist/css/jquery.fancybox.css +0 -222
  39. data/node_modules/fancybox/dist/helpers/css/jquery.fancybox-buttons.css +0 -82
  40. data/node_modules/fancybox/dist/helpers/css/jquery.fancybox-thumbs.css +0 -46
  41. data/node_modules/fancybox/dist/helpers/img/fancybox_buttons.png +0 -0
  42. data/node_modules/fancybox/dist/helpers/js/jquery.fancybox-buttons.cjs.js +0 -121
  43. data/node_modules/fancybox/dist/helpers/js/jquery.fancybox-buttons.js +0 -122
  44. data/node_modules/fancybox/dist/helpers/js/jquery.fancybox-media.cjs.js +0 -199
  45. data/node_modules/fancybox/dist/helpers/js/jquery.fancybox-media.js +0 -199
  46. data/node_modules/fancybox/dist/helpers/js/jquery.fancybox-thumbs.cjs.js +0 -164
  47. data/node_modules/fancybox/dist/helpers/js/jquery.fancybox-thumbs.js +0 -165
  48. data/node_modules/fancybox/dist/helpers/scss/jquery.fancybox-buttons.scss +0 -100
  49. data/node_modules/fancybox/dist/helpers/scss/jquery.fancybox-thumbs.scss +0 -55
  50. data/node_modules/fancybox/dist/img/blank.gif +0 -0
  51. data/node_modules/fancybox/dist/img/fancybox_loading.gif +0 -0
  52. data/node_modules/fancybox/dist/img/fancybox_loading@2x.gif +0 -0
  53. data/node_modules/fancybox/dist/img/fancybox_overlay.png +0 -0
  54. data/node_modules/fancybox/dist/img/fancybox_sprite.png +0 -0
  55. data/node_modules/fancybox/dist/img/fancybox_sprite@2x.png +0 -0
  56. data/node_modules/fancybox/dist/js/jquery.fancybox.cjs.js +0 -2027
  57. data/node_modules/fancybox/dist/js/jquery.fancybox.js +0 -2018
  58. data/node_modules/fancybox/dist/js/jquery.fancybox.pack.js +0 -46
  59. data/node_modules/fancybox/dist/scss/jquery.fancybox.scss +0 -276
  60. data/node_modules/fancybox/fancybox.jquery.json +0 -31
  61. data/node_modules/fancybox/lib/jquery-1.10.2.min.js +0 -6
  62. data/node_modules/fancybox/lib/jquery.mousewheel.pack.js +0 -14
  63. data/node_modules/fancybox/package.json +0 -32
  64. data/node_modules/fancybox/sprite.psd +0 -0
  65. data/node_modules/fancybox/test.js +0 -10
@@ -1,5 +1,5 @@
1
1
  // ==================================================
2
- // fancyBox v3.3.5
2
+ // fancyBox v3.5.2
3
3
  //
4
4
  // Licensed GPLv3 for open source use
5
5
  // or fancyBox Commercial License for commercial use
@@ -35,6 +35,10 @@
35
35
  // ========================
36
36
 
37
37
  var defaults = {
38
+ // Close existing modals
39
+ // Set this to false if you do not need to stack multiple instances
40
+ closeExisting: false,
41
+
38
42
  // Enable infinite gallery navigation
39
43
  loop: false,
40
44
 
@@ -44,6 +48,9 @@
44
48
  // Enable keyboard navigation
45
49
  keyboard: true,
46
50
 
51
+ // Should allow caption to overlap the content
52
+ preventCaptionOverlap: true,
53
+
47
54
  // Should display navigation arrows at the screen edges
48
55
  arrows: true,
49
56
 
@@ -66,7 +73,7 @@
66
73
  buttons: [
67
74
  "zoom",
68
75
  //"share",
69
- //"slideShow",
76
+ "slideShow",
70
77
  //"fullScreen",
71
78
  //"download",
72
79
  "thumbs",
@@ -104,7 +111,7 @@
104
111
  iframe: {
105
112
  // Iframe template
106
113
  tpl:
107
- '<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>',
114
+ '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" allowfullscreen allow="autoplay; fullscreen" src=""></iframe>',
108
115
 
109
116
  // Preload iframe before displaying it
110
117
  // This allows to calculate iframe content width and height
@@ -121,6 +128,17 @@
121
128
  }
122
129
  },
123
130
 
131
+ // For HTML5 video only
132
+ video: {
133
+ tpl:
134
+ '<video class="fancybox-video" controls controlsList="nodownload" poster="{{poster}}">' +
135
+ '<source src="{{src}}" type="{{format}}" />' +
136
+ 'Sorry, your browser doesn\'t support embedded videos, <a href="{{src}}">download</a> and watch with your favorite video player!' +
137
+ "</video>",
138
+ format: "", // custom video format
139
+ autoStart: true
140
+ },
141
+
124
142
  // Default content type if cannot be detected automatically
125
143
  defaultType: "image",
126
144
 
@@ -167,9 +185,7 @@
167
185
  '<div class="fancybox-container" role="dialog" tabindex="-1">' +
168
186
  '<div class="fancybox-bg"></div>' +
169
187
  '<div class="fancybox-inner">' +
170
- '<div class="fancybox-infobar">' +
171
- "<span data-fancybox-index></span>&nbsp;/&nbsp;<span data-fancybox-count></span>" +
172
- "</div>" +
188
+ '<div class="fancybox-infobar"><span data-fancybox-index></span>&nbsp;/&nbsp;<span data-fancybox-count></span></div>' +
173
189
  '<div class="fancybox-toolbar">{{buttons}}</div>' +
174
190
  '<div class="fancybox-navigation">{{arrows}}</div>' +
175
191
  '<div class="fancybox-stage"></div>' +
@@ -186,54 +202,49 @@
186
202
  btnTpl: {
187
203
  download:
188
204
  '<a download data-fancybox-download class="fancybox-button fancybox-button--download" title="{{DOWNLOAD}}" href="javascript:;">' +
189
- '<svg viewBox="0 0 40 40">' +
190
- '<path d="M13,16 L20,23 L27,16 M20,7 L20,23 M10,24 L10,28 L30,28 L30,24" />' +
191
- "</svg>" +
205
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.62 17.09V19H5.38v-1.91zm-2.97-6.96L17 11.45l-5 4.87-5-4.87 1.36-1.32 2.68 2.64V5h1.92v7.77z"/></svg>' +
192
206
  "</a>",
193
207
 
194
208
  zoom:
195
209
  '<button data-fancybox-zoom class="fancybox-button fancybox-button--zoom" title="{{ZOOM}}">' +
196
- '<svg viewBox="0 0 40 40">' +
197
- '<path d="M18,17 m-8,0 a8,8 0 1,0 16,0 a8,8 0 1,0 -16,0 M24,22 L31,29" />' +
198
- "</svg>" +
210
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.7 17.3l-3-3a5.9 5.9 0 0 0-.6-7.6 5.9 5.9 0 0 0-8.4 0 5.9 5.9 0 0 0 0 8.4 5.9 5.9 0 0 0 7.7.7l3 3a1 1 0 0 0 1.3 0c.4-.5.4-1 0-1.5zM8.1 13.8a4 4 0 0 1 0-5.7 4 4 0 0 1 5.7 0 4 4 0 0 1 0 5.7 4 4 0 0 1-5.7 0z"/></svg>' +
199
211
  "</button>",
200
212
 
201
213
  close:
202
214
  '<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}">' +
203
- '<svg viewBox="0 0 40 40">' +
204
- '<path d="M10,10 L30,30 M30,10 L10,30" />' +
205
- "</svg>" +
215
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 10.6L6.6 5.2 5.2 6.6l5.4 5.4-5.4 5.4 1.4 1.4 5.4-5.4 5.4 5.4 1.4-1.4-5.4-5.4 5.4-5.4-1.4-1.4-5.4 5.4z"/></svg>' +
206
216
  "</button>",
207
217
 
208
- // This small close button will be appended to your html/inline/ajax content by default,
209
- // if "smallBtn" option is not set to false
210
- smallBtn:
211
- '<button data-fancybox-close class="fancybox-close-small" title="{{CLOSE}}"><svg viewBox="0 0 32 32"><path d="M10,10 L22,22 M22,10 L10,22"></path></svg></button>',
212
-
213
218
  // Arrows
214
219
  arrowLeft:
215
- '<a data-fancybox-prev class="fancybox-button fancybox-button--arrow_left" title="{{PREV}}" href="javascript:;">' +
216
- '<svg viewBox="0 0 40 40">' +
217
- '<path d="M18,12 L10,20 L18,28 M10,20 L30,20"></path>' +
218
- "</svg>" +
219
- "</a>",
220
+ '<button data-fancybox-prev class="fancybox-button fancybox-button--arrow_left" title="{{PREV}}">' +
221
+ '<div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11.28 15.7l-1.34 1.37L5 12l4.94-5.07 1.34 1.38-2.68 2.72H19v1.94H8.6z"/></svg></div>' +
222
+ "</button>",
220
223
 
221
224
  arrowRight:
222
- '<a data-fancybox-next class="fancybox-button fancybox-button--arrow_right" title="{{NEXT}}" href="javascript:;">' +
223
- '<svg viewBox="0 0 40 40">' +
224
- '<path d="M10,20 L30,20 M22,12 L30,20 L22,28"></path>' +
225
- "</svg>" +
226
- "</a>"
225
+ '<button data-fancybox-next class="fancybox-button fancybox-button--arrow_right" title="{{NEXT}}">' +
226
+ '<div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.4 12.97l-2.68 2.72 1.34 1.38L19 12l-4.94-5.07-1.34 1.38 2.68 2.72H5v1.94z"/></svg></div>' +
227
+ "</button>",
228
+
229
+ // This small close button will be appended to your html/inline/ajax content by default,
230
+ // if "smallBtn" option is not set to false
231
+ smallBtn:
232
+ '<button type="button" data-fancybox-close class="fancybox-button fancybox-close-small" title="{{CLOSE}}">' +
233
+ '<svg xmlns="http://www.w3.org/2000/svg" version="1" viewBox="0 0 24 24"><path d="M13 12l5-5-1-1-5 5-5-5-1 1 5 5-5 5 1 1 5-5 5 5 1-1z"/></svg>' +
234
+ "</button>"
227
235
  },
228
236
 
229
237
  // Container is injected into this element
230
238
  parentEl: "body",
231
239
 
240
+ // Hide browser vertical scrollbars; use at your own risk
241
+ hideScrollbar: true,
242
+
232
243
  // Focus handling
233
244
  // ==============
234
245
 
235
246
  // Try to focus on the first focusable element after opening
236
- autoFocus: false,
247
+ autoFocus: true,
237
248
 
238
249
  // Put focus back to active element after closing
239
250
  backFocus: true,
@@ -248,7 +259,7 @@
248
259
  autoStart: false
249
260
  },
250
261
 
251
- // Set `touch: false` to disable dragging/swiping
262
+ // Set `touch: false` to disable panning/swiping
252
263
  touch: {
253
264
  vertical: true, // Allow to drag content vertically
254
265
  momentum: true // Continue movement after releasing mouse/touch when panning
@@ -261,19 +272,19 @@
261
272
  // Customize or add new media types
262
273
  // Example:
263
274
  /*
264
- media : {
265
- youtube : {
266
- params : {
267
- autoplay : 0
268
- }
269
- }
275
+ media : {
276
+ youtube : {
277
+ params : {
278
+ autoplay : 0
279
+ }
270
280
  }
271
- */
281
+ }
282
+ */
272
283
  media: {},
273
284
 
274
285
  slideShow: {
275
286
  autoStart: false,
276
- speed: 4000
287
+ speed: 3000
277
288
  },
278
289
 
279
290
  thumbs: {
@@ -293,11 +304,11 @@
293
304
  // See Documentation/API/Events for more information
294
305
  // Example:
295
306
  /*
296
- afterShow: function( instance, current ) {
297
- console.info( 'Clicked element:' );
298
- console.info( current.opts.$orig );
299
- }
300
- */
307
+ afterShow: function( instance, current ) {
308
+ console.info( 'Clicked element:' );
309
+ console.info( current.opts.$orig );
310
+ }
311
+ */
301
312
 
302
313
  onInit: $.noop, // When instance has been initialized
303
314
 
@@ -348,6 +359,7 @@
348
359
  // =============================================
349
360
 
350
361
  mobile: {
362
+ preventCaptionOverlap: false,
351
363
  idleTime: false,
352
364
  clickContent: function(current, event) {
353
365
  return current.type === "image" ? "toggleControls" : false;
@@ -426,6 +438,18 @@
426
438
  );
427
439
  })();
428
440
 
441
+ var cancelAFrame = (function() {
442
+ return (
443
+ window.cancelAnimationFrame ||
444
+ window.webkitCancelAnimationFrame ||
445
+ window.mozCancelAnimationFrame ||
446
+ window.oCancelAnimationFrame ||
447
+ function(id) {
448
+ window.clearTimeout(id);
449
+ }
450
+ );
451
+ })();
452
+
429
453
  // Detect the supported transition-end event property name
430
454
  // =======================================================
431
455
  var transitionEnd = (function() {
@@ -469,6 +493,30 @@
469
493
  return rez;
470
494
  };
471
495
 
496
+ // How much of an element is visible in viewport
497
+ // =============================================
498
+
499
+ var inViewport = function(elem) {
500
+ var elemCenter, rez;
501
+
502
+ if (!elem || elem.ownerDocument !== document) {
503
+ return false;
504
+ }
505
+
506
+ $(".fancybox-container").css("pointer-events", "none");
507
+
508
+ elemCenter = {
509
+ x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
510
+ y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
511
+ };
512
+
513
+ rez = document.elementFromPoint(elemCenter.x, elemCenter.y) === elem;
514
+
515
+ $(".fancybox-container").css("pointer-events", "");
516
+
517
+ return rez;
518
+ };
519
+
472
520
  // Class definition
473
521
  // ================
474
522
 
@@ -508,9 +556,6 @@
508
556
  return;
509
557
  }
510
558
 
511
- // Save last active element
512
- self.$lastFocus = $(document.activeElement).trigger("blur");
513
-
514
559
  self.init();
515
560
  };
516
561
 
@@ -522,34 +567,31 @@
522
567
  var self = this,
523
568
  firstItem = self.group[self.currIndex],
524
569
  firstItemOpts = firstItem.opts,
525
- scrollbarWidth = $.fancybox.scrollbarWidth,
526
- $scrollDiv,
527
570
  $container,
528
571
  buttonStr;
529
572
 
573
+ if (firstItemOpts.closeExisting) {
574
+ $.fancybox.close(true);
575
+ }
576
+
530
577
  // Hide scrollbars
531
578
  // ===============
532
579
 
533
- if (!$.fancybox.getInstance() && firstItemOpts.hideScrollbar !== false) {
534
- $("body").addClass("fancybox-active");
535
-
536
- if (!$.fancybox.isMobile && document.body.scrollHeight > window.innerHeight) {
537
- if (scrollbarWidth === undefined) {
538
- $scrollDiv = $('<div style="width:100px;height:100px;overflow:scroll;" />').appendTo("body");
539
-
540
- scrollbarWidth = $.fancybox.scrollbarWidth = $scrollDiv[0].offsetWidth - $scrollDiv[0].clientWidth;
541
-
542
- $scrollDiv.remove();
543
- }
580
+ $("body").addClass("fancybox-active");
544
581
 
545
- $("head").append(
546
- '<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar { margin-right: ' +
547
- scrollbarWidth +
548
- "px; }</style>"
549
- );
582
+ if (
583
+ !$.fancybox.getInstance() &&
584
+ firstItemOpts.hideScrollbar !== false &&
585
+ !$.fancybox.isMobile &&
586
+ document.body.scrollHeight > window.innerHeight
587
+ ) {
588
+ $("head").append(
589
+ '<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar{margin-right:' +
590
+ (window.innerWidth - document.documentElement.clientWidth) +
591
+ "px;}</style>"
592
+ );
550
593
 
551
- $("body").addClass("compensate-for-scrollbar");
552
- }
594
+ $("body").addClass("compensate-for-scrollbar");
553
595
  }
554
596
 
555
597
  // Build html markup and set references
@@ -573,7 +615,6 @@
573
615
  )
574
616
  )
575
617
  .attr("id", "fancybox-container-" + self.id)
576
- .addClass("fancybox-is-hidden")
577
618
  .addClass(firstItemOpts.baseClass)
578
619
  .data("FancyBox", self)
579
620
  .appendTo(firstItemOpts.parentEl);
@@ -601,7 +642,7 @@
601
642
  // ============================================================
602
643
 
603
644
  translate: function(obj, str) {
604
- var arr = obj.opts.i18n[obj.opts.lang];
645
+ var arr = obj.opts.i18n[obj.opts.lang] || obj.opts.i18n.en;
605
646
 
606
647
  return str.replace(/\{\{(\w+)\}\}/g, function(match, n) {
607
648
  var value = arr[n];
@@ -677,6 +718,10 @@
677
718
  obj.opts.buttons = opts.buttons;
678
719
  }
679
720
 
721
+ if ($.fancybox.isMobile && obj.opts.mobile) {
722
+ obj.opts = mergeOpts(obj.opts, obj.opts.mobile);
723
+ }
724
+
680
725
  // Step 2 - Make sure we have content type, if not - try to guess
681
726
  // ==============================================================
682
727
 
@@ -684,16 +729,17 @@
684
729
  src = obj.src || "";
685
730
 
686
731
  if (!type && src) {
687
- if ((found = src.match(/\.(mp4|mov|ogv)((\?|#).*)?$/i))) {
732
+ if ((found = src.match(/\.(mp4|mov|ogv|webm)((\?|#).*)?$/i))) {
688
733
  type = "video";
689
734
 
690
- if (!obj.opts.videoFormat) {
691
- obj.opts.videoFormat = "video/" + (found[1] === "ogv" ? "ogg" : found[1]);
735
+ if (!obj.opts.video.format) {
736
+ obj.opts.video.format = "video/" + (found[1] === "ogv" ? "ogg" : found[1]);
692
737
  }
693
738
  } else if (src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i)) {
694
739
  type = "image";
695
740
  } else if (src.match(/\.(pdf)((\?|#).*)?$/i)) {
696
741
  type = "iframe";
742
+ obj = $.extend(true, obj, {contentType: "pdf", opts: {iframe: {preload: false}}});
697
743
  } else if (src.charAt(0) === "#") {
698
744
  type = "inline";
699
745
  }
@@ -722,16 +768,28 @@
722
768
  obj.opts.toolbar = !obj.opts.smallBtn;
723
769
  }
724
770
 
725
- // Find thumbnail image
771
+ // Find thumbnail image, check if exists and if is in the viewport
772
+ obj.$thumb = obj.opts.$thumb || null;
773
+
726
774
  if (obj.opts.$trigger && obj.index === self.opts.index) {
727
- obj.opts.$thumb = obj.opts.$trigger.find("img:first");
775
+ obj.$thumb = obj.opts.$trigger.find("img:first");
776
+
777
+ if (obj.$thumb.length) {
778
+ obj.opts.$orig = obj.opts.$trigger;
779
+ }
728
780
  }
729
781
 
730
- if ((!obj.opts.$thumb || !obj.opts.$thumb.length) && obj.opts.$orig) {
731
- obj.opts.$thumb = obj.opts.$orig.find("img:first");
782
+ if (!(obj.$thumb && obj.$thumb.length) && obj.opts.$orig) {
783
+ obj.$thumb = obj.opts.$orig.find("img:first");
732
784
  }
733
785
 
734
- // "caption" is a "special" option, it can be used to customize caption per gallery item ..
786
+ if (obj.$thumb && !obj.$thumb.length) {
787
+ obj.$thumb = null;
788
+ }
789
+
790
+ obj.thumb = obj.opts.thumb || (obj.$thumb ? obj.$thumb[0].src : null);
791
+
792
+ // "caption" is a "special" option, it can be used to customize caption per gallery item
735
793
  if ($.type(obj.opts.caption) === "function") {
736
794
  obj.opts.caption = obj.opts.caption.apply(item, [self, obj]);
737
795
  }
@@ -760,6 +818,7 @@
760
818
  // Hide all buttons and disable interactivity for modal items
761
819
  if (obj.opts.modal) {
762
820
  obj.opts = $.extend(true, obj.opts, {
821
+ trapFocus: true,
763
822
  // Remove buttons
764
823
  infobar: 0,
765
824
  toolbar: 0,
@@ -811,7 +870,7 @@
811
870
  // - browser scrolling, resizing;
812
871
  // - focusing
813
872
  // - keyboard
814
- // - detect idle
873
+ // - detecting inactivity
815
874
  // ======================================
816
875
 
817
876
  addEvents: function() {
@@ -820,6 +879,8 @@
820
879
  self.removeEvents();
821
880
 
822
881
  // Make navigation elements clickable
882
+ // ==================================
883
+
823
884
  self.$refs.container
824
885
  .on("click.fb-close", "[data-fancybox-close]", function(e) {
825
886
  e.stopPropagation();
@@ -845,54 +906,50 @@
845
906
  });
846
907
 
847
908
  // Handle page scrolling and browser resizing
909
+ // ==========================================
910
+
848
911
  $W.on("orientationchange.fb resize.fb", function(e) {
849
912
  if (e && e.originalEvent && e.originalEvent.type === "resize") {
850
- requestAFrame(function() {
851
- self.update();
913
+ if (self.requestId) {
914
+ cancelAFrame(self.requestId);
915
+ }
916
+
917
+ self.requestId = requestAFrame(function() {
918
+ self.update(e);
852
919
  });
853
920
  } else {
854
- self.$refs.stage.hide();
921
+ if (self.current && self.current.type === "iframe") {
922
+ self.$refs.stage.hide();
923
+ }
855
924
 
856
925
  setTimeout(function() {
857
926
  self.$refs.stage.show();
858
927
 
859
- self.update();
928
+ self.update(e);
860
929
  }, $.fancybox.isMobile ? 600 : 250);
861
930
  }
862
931
  });
863
932
 
864
- // Trap keyboard focus inside of the modal, so the user does not accidentally tab outside of the modal
865
- // (a.k.a. "escaping the modal")
866
- $D.on("focusin.fb", function(e) {
867
- var instance = $.fancybox ? $.fancybox.getInstance() : null;
868
-
869
- if (
870
- instance.isClosing ||
871
- !instance.current ||
872
- !instance.current.opts.trapFocus ||
873
- $(e.target).hasClass("fancybox-container") ||
874
- $(e.target).is(document)
875
- ) {
876
- return;
877
- }
878
-
879
- if (instance && $(e.target).css("position") !== "fixed" && !instance.$refs.container.has(e.target).length) {
880
- e.stopPropagation();
881
-
882
- instance.focus();
883
- }
884
- });
885
-
886
- // Enable keyboard navigation
887
933
  $D.on("keydown.fb", function(e) {
888
- var current = self.current,
934
+ var instance = $.fancybox ? $.fancybox.getInstance() : null,
935
+ current = instance.current,
889
936
  keycode = e.keyCode || e.which;
890
937
 
891
- if (!current || !current.opts.keyboard) {
938
+ // Trap keyboard focus inside of the modal
939
+ // =======================================
940
+
941
+ if (keycode == 9) {
942
+ if (current.opts.trapFocus) {
943
+ self.focus(e);
944
+ }
945
+
892
946
  return;
893
947
  }
894
948
 
895
- if (e.ctrlKey || e.altKey || e.shiftKey || $(e.target).is("input") || $(e.target).is("textarea")) {
949
+ // Enable keyboard navigation
950
+ // ==========================
951
+
952
+ if (!current.opts.keyboard || e.ctrlKey || e.altKey || e.shiftKey || $(e.target).is("input") || $(e.target).is("textarea")) {
896
953
  return;
897
954
  }
898
955
 
@@ -963,7 +1020,7 @@
963
1020
  var self = this;
964
1021
 
965
1022
  $W.off("orientationchange.fb resize.fb");
966
- $D.off("focusin.fb keydown.fb .fb-idle");
1023
+ $D.off("keydown.fb .fb-idle");
967
1024
 
968
1025
  this.$refs.container.off(".fb-close .fb-prev .fb-next");
969
1026
 
@@ -995,48 +1052,46 @@
995
1052
  var self = this,
996
1053
  groupLen = self.group.length,
997
1054
  firstRun,
1055
+ isMoved,
998
1056
  loop,
999
1057
  current,
1000
1058
  previous,
1001
- canvasWidth,
1002
- currentPos,
1003
- transitionProps;
1059
+ slidePos,
1060
+ stagePos,
1061
+ prop,
1062
+ diff;
1004
1063
 
1005
1064
  if (self.isDragging || self.isClosing || (self.isAnimating && self.firstRun)) {
1006
1065
  return;
1007
1066
  }
1008
1067
 
1009
- pos = parseInt(pos, 10);
1010
-
1011
1068
  // Should loop?
1069
+ pos = parseInt(pos, 10);
1012
1070
  loop = self.current ? self.current.opts.loop : self.opts.loop;
1013
1071
 
1014
1072
  if (!loop && (pos < 0 || pos >= groupLen)) {
1015
1073
  return false;
1016
1074
  }
1017
1075
 
1076
+ // Check if opening for the first time; this helps to speed things up
1018
1077
  firstRun = self.firstRun = !Object.keys(self.slides).length;
1019
1078
 
1020
- if (groupLen < 2 && !firstRun && !!self.isDragging) {
1021
- return;
1022
- }
1023
-
1079
+ // Create slides
1024
1080
  previous = self.current;
1025
1081
 
1026
1082
  self.prevIndex = self.currIndex;
1027
1083
  self.prevPos = self.currPos;
1028
1084
 
1029
- // Create slides
1030
1085
  current = self.createSlide(pos);
1031
1086
 
1032
1087
  if (groupLen > 1) {
1033
- if (loop || current.index > 0) {
1034
- self.createSlide(pos - 1);
1035
- }
1036
-
1037
1088
  if (loop || current.index < groupLen - 1) {
1038
1089
  self.createSlide(pos + 1);
1039
1090
  }
1091
+
1092
+ if (loop || current.index > 0) {
1093
+ self.createSlide(pos - 1);
1094
+ }
1040
1095
  }
1041
1096
 
1042
1097
  self.current = current;
@@ -1047,10 +1102,6 @@
1047
1102
 
1048
1103
  self.updateControls();
1049
1104
 
1050
- currentPos = $.fancybox.getTranslate(current.$slide);
1051
-
1052
- current.isMoved = (currentPos.left !== 0 || currentPos.top !== 0) && !current.$slide.hasClass("fancybox-animated");
1053
-
1054
1105
  // Validate duration length
1055
1106
  current.forcedDuration = undefined;
1056
1107
 
@@ -1062,73 +1113,105 @@
1062
1113
 
1063
1114
  duration = parseInt(duration, 10);
1064
1115
 
1116
+ // Check if user has swiped the slides or if still animating
1117
+ isMoved = self.isMoved(current);
1118
+
1119
+ // Make sure current slide is visible
1120
+ current.$slide.addClass("fancybox-slide--current");
1121
+
1065
1122
  // Fresh start - reveal container, current slide and start loading content
1066
1123
  if (firstRun) {
1067
1124
  if (current.opts.animationEffect && duration) {
1068
1125
  self.$refs.container.css("transition-duration", duration + "ms");
1069
1126
  }
1070
1127
 
1071
- self.$refs.container.removeClass("fancybox-is-hidden");
1128
+ self.$refs.container.addClass("fancybox-is-open").trigger("focus");
1072
1129
 
1073
- forceRedraw(self.$refs.container);
1074
-
1075
- self.$refs.container.addClass("fancybox-is-open");
1076
-
1077
- forceRedraw(self.$refs.container);
1078
-
1079
- // Make current slide visible
1080
- current.$slide.addClass("fancybox-slide--previous");
1081
-
1082
- // Attempt to load content into slide;
1083
- // at this point image would start loading, but inline/html content would load immediately
1130
+ // Attempt to load content into slide
1131
+ // This will later call `afterLoad` -> `revealContent`
1084
1132
  self.loadSlide(current);
1085
1133
 
1086
- current.$slide.removeClass("fancybox-slide--previous").addClass("fancybox-slide--current");
1087
-
1088
1134
  self.preload("image");
1089
1135
 
1090
1136
  return;
1091
1137
  }
1092
1138
 
1093
- // Clean up
1139
+ // Get actual slide/stage positions (before cleaning up)
1140
+ slidePos = $.fancybox.getTranslate(previous.$slide);
1141
+ stagePos = $.fancybox.getTranslate(self.$refs.stage);
1142
+
1143
+ // Clean up all slides
1094
1144
  $.each(self.slides, function(index, slide) {
1095
- $.fancybox.stop(slide.$slide);
1145
+ $.fancybox.stop(slide.$slide, true);
1096
1146
  });
1097
1147
 
1098
- // Make current that slide is visible even if content is still loading
1099
- current.$slide.removeClass("fancybox-slide--next fancybox-slide--previous").addClass("fancybox-slide--current");
1148
+ if (previous.pos !== current.pos) {
1149
+ previous.isComplete = false;
1150
+ }
1151
+
1152
+ previous.$slide.removeClass("fancybox-slide--complete fancybox-slide--current");
1100
1153
 
1101
- // If slides have been dragged, animate them to correct position
1102
- if (current.isMoved) {
1103
- canvasWidth = Math.round(current.$slide.width());
1154
+ // If slides are out of place, then animate them to correct position
1155
+ if (isMoved) {
1156
+ // Calculate horizontal swipe distance
1157
+ diff = slidePos.left - (previous.pos * slidePos.width + previous.pos * previous.opts.gutter);
1104
1158
 
1105
1159
  $.each(self.slides, function(index, slide) {
1106
- var pos = slide.pos - current.pos;
1160
+ slide.$slide.removeClass("fancybox-animated").removeClass(function(index, className) {
1161
+ return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" ");
1162
+ });
1163
+
1164
+ // Make sure that each slide is in equal distance
1165
+ // This is mostly needed for freshly added slides, because they are not yet positioned
1166
+ var leftPos = slide.pos * slidePos.width + slide.pos * slide.opts.gutter;
1167
+
1168
+ $.fancybox.setTranslate(slide.$slide, {top: 0, left: leftPos - stagePos.left + diff});
1169
+
1170
+ if (slide.pos !== current.pos) {
1171
+ slide.$slide.addClass("fancybox-slide--" + (slide.pos > current.pos ? "next" : "previous"));
1172
+ }
1173
+
1174
+ // Redraw to make sure that transition will start
1175
+ forceRedraw(slide.$slide);
1107
1176
 
1177
+ // Animate the slide
1108
1178
  $.fancybox.animate(
1109
1179
  slide.$slide,
1110
1180
  {
1111
1181
  top: 0,
1112
- left: pos * canvasWidth + pos * slide.opts.gutter
1182
+ left: (slide.pos - current.pos) * slidePos.width + (slide.pos - current.pos) * slide.opts.gutter
1113
1183
  },
1114
1184
  duration,
1115
1185
  function() {
1116
- slide.$slide.removeAttr("style").removeClass("fancybox-slide--next fancybox-slide--previous");
1186
+ slide.$slide
1187
+ .css({
1188
+ transform: "",
1189
+ opacity: ""
1190
+ })
1191
+ .removeClass("fancybox-slide--next fancybox-slide--previous");
1117
1192
 
1118
1193
  if (slide.pos === self.currPos) {
1119
- current.isMoved = false;
1120
-
1121
1194
  self.complete();
1122
1195
  }
1123
1196
  }
1124
1197
  );
1125
1198
  });
1126
- } else {
1127
- self.$refs.stage.children().removeAttr("style");
1128
- }
1199
+ } else if (duration && current.opts.transitionEffect) {
1200
+ // Set transition effect for previously active slide
1201
+ prop = "fancybox-animated fancybox-fx-" + current.opts.transitionEffect;
1129
1202
 
1130
- // Start transition that reveals current content
1131
- // or wait when it will be loaded
1203
+ previous.$slide.addClass("fancybox-slide--" + (previous.pos > current.pos ? "next" : "previous"));
1204
+
1205
+ $.fancybox.animate(
1206
+ previous.$slide,
1207
+ prop,
1208
+ duration,
1209
+ function() {
1210
+ previous.$slide.removeClass(prop).removeClass("fancybox-slide--next fancybox-slide--previous");
1211
+ },
1212
+ false
1213
+ );
1214
+ }
1132
1215
 
1133
1216
  if (current.isLoaded) {
1134
1217
  self.revealContent(current);
@@ -1137,33 +1220,6 @@
1137
1220
  }
1138
1221
 
1139
1222
  self.preload("image");
1140
-
1141
- if (previous.pos === current.pos) {
1142
- return;
1143
- }
1144
-
1145
- // Handle previous slide
1146
- // =====================
1147
-
1148
- transitionProps = "fancybox-slide--" + (previous.pos > current.pos ? "next" : "previous");
1149
-
1150
- previous.$slide.removeClass("fancybox-slide--complete fancybox-slide--current fancybox-slide--next fancybox-slide--previous");
1151
-
1152
- previous.isComplete = false;
1153
-
1154
- if (!duration || (!current.isMoved && !current.opts.transitionEffect)) {
1155
- return;
1156
- }
1157
-
1158
- if (current.isMoved) {
1159
- previous.$slide.addClass(transitionProps);
1160
- } else {
1161
- transitionProps = "fancybox-animated " + transitionProps + " fancybox-fx-" + current.opts.transitionEffect;
1162
-
1163
- $.fancybox.animate(previous.$slide, transitionProps, duration, function() {
1164
- previous.$slide.removeClass(transitionProps).removeAttr("style");
1165
- });
1166
- }
1167
1223
  },
1168
1224
 
1169
1225
  // Create new "slide" element
@@ -1211,14 +1267,14 @@
1211
1267
  scaleX,
1212
1268
  scaleY;
1213
1269
 
1214
- if (self.isAnimating || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
1270
+ if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
1215
1271
  return;
1216
1272
  }
1217
1273
 
1218
- $.fancybox.stop($content);
1219
-
1220
1274
  self.isAnimating = true;
1221
1275
 
1276
+ $.fancybox.stop($content);
1277
+
1222
1278
  x = x === undefined ? canvasWidth * 0.5 : x;
1223
1279
  y = y === undefined ? canvasHeight * 0.5 : y;
1224
1280
 
@@ -1290,14 +1346,14 @@
1290
1346
  $content = current.$content,
1291
1347
  end;
1292
1348
 
1293
- if (self.isAnimating || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
1349
+ if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
1294
1350
  return;
1295
1351
  }
1296
1352
 
1297
- $.fancybox.stop($content);
1298
-
1299
1353
  self.isAnimating = true;
1300
1354
 
1355
+ $.fancybox.stop($content);
1356
+
1301
1357
  end = self.getFitPos(current);
1302
1358
 
1303
1359
  self.updateCursor(end.width, end.height);
@@ -1323,12 +1379,12 @@
1323
1379
  getFitPos: function(slide) {
1324
1380
  var self = this,
1325
1381
  $content = slide.$content,
1382
+ $slide = slide.$slide,
1326
1383
  width = slide.width || slide.opts.width,
1327
1384
  height = slide.height || slide.opts.height,
1328
1385
  maxWidth,
1329
1386
  maxHeight,
1330
1387
  minRatio,
1331
- margin,
1332
1388
  aspectRatio,
1333
1389
  rez = {};
1334
1390
 
@@ -1336,16 +1392,20 @@
1336
1392
  return false;
1337
1393
  }
1338
1394
 
1339
- margin = {
1340
- top: parseInt(slide.$slide.css("paddingTop"), 10),
1341
- right: parseInt(slide.$slide.css("paddingRight"), 10),
1342
- bottom: parseInt(slide.$slide.css("paddingBottom"), 10),
1343
- left: parseInt(slide.$slide.css("paddingLeft"), 10)
1344
- };
1395
+ maxWidth = $.fancybox.getTranslate(self.$refs.stage).width;
1396
+ maxHeight = $.fancybox.getTranslate(self.$refs.stage).height;
1397
+
1398
+ maxWidth -=
1399
+ parseFloat($slide.css("paddingLeft")) +
1400
+ parseFloat($slide.css("paddingRight")) +
1401
+ parseFloat($content.css("marginLeft")) +
1402
+ parseFloat($content.css("marginRight"));
1345
1403
 
1346
- // We can not use $slide width here, because it can have different diemensions while in transiton
1347
- maxWidth = parseInt(self.$refs.stage.width(), 10) - (margin.left + margin.right);
1348
- maxHeight = parseInt(self.$refs.stage.height(), 10) - (margin.top + margin.bottom);
1404
+ maxHeight -=
1405
+ parseFloat($slide.css("paddingTop")) +
1406
+ parseFloat($slide.css("paddingBottom")) +
1407
+ parseFloat($content.css("marginTop")) +
1408
+ parseFloat($content.css("marginBottom"));
1349
1409
 
1350
1410
  if (!width || !height) {
1351
1411
  width = maxWidth;
@@ -1354,13 +1414,21 @@
1354
1414
 
1355
1415
  minRatio = Math.min(1, maxWidth / width, maxHeight / height);
1356
1416
 
1357
- // Use floor rounding to make sure it really fits
1358
- width = Math.floor(minRatio * width);
1359
- height = Math.floor(minRatio * height);
1417
+ width = minRatio * width;
1418
+ height = minRatio * height;
1419
+
1420
+ // Adjust width/height to precisely fit into container
1421
+ if (width > maxWidth - 0.5) {
1422
+ width = maxWidth;
1423
+ }
1424
+
1425
+ if (height > maxHeight - 0.5) {
1426
+ height = maxHeight;
1427
+ }
1360
1428
 
1361
1429
  if (slide.type === "image") {
1362
- rez.top = Math.floor((maxHeight - height) * 0.5) + margin.top;
1363
- rez.left = Math.floor((maxWidth - width) * 0.5) + margin.left;
1430
+ rez.top = Math.floor((maxHeight - height) * 0.5) + parseFloat($slide.css("paddingTop"));
1431
+ rez.left = Math.floor((maxWidth - width) * 0.5) + parseFloat($slide.css("paddingLeft"));
1364
1432
  } else if (slide.contentType === "video") {
1365
1433
  // Force aspect ratio for the video
1366
1434
  // "I say the whole world must learn of our peaceful ways… by force!"
@@ -1382,23 +1450,28 @@
1382
1450
  // Update content size and position for all slides
1383
1451
  // ==============================================
1384
1452
 
1385
- update: function() {
1453
+ update: function(e) {
1386
1454
  var self = this;
1387
1455
 
1388
1456
  $.each(self.slides, function(key, slide) {
1389
- self.updateSlide(slide);
1457
+ self.updateSlide(slide, e);
1390
1458
  });
1391
1459
  },
1392
1460
 
1393
1461
  // Update slide content position and size
1394
1462
  // ======================================
1395
1463
 
1396
- updateSlide: function(slide, duration) {
1464
+ updateSlide: function(slide, e) {
1397
1465
  var self = this,
1398
1466
  $content = slide && slide.$content,
1399
1467
  width = slide.width || slide.opts.width,
1400
- height = slide.height || slide.opts.height;
1468
+ height = slide.height || slide.opts.height,
1469
+ $slide = slide.$slide;
1401
1470
 
1471
+ // First, prevent caption overlap, if needed
1472
+ self.adjustCaption(slide);
1473
+
1474
+ // Then resize content to fit inside the slide
1402
1475
  if ($content && (width || height || slide.contentType === "video") && !slide.hasError) {
1403
1476
  $.fancybox.stop($content);
1404
1477
 
@@ -1411,37 +1484,86 @@
1411
1484
  }
1412
1485
  }
1413
1486
 
1414
- slide.$slide.trigger("refresh");
1487
+ // Then some adjustments
1488
+ self.adjustLayout(slide);
1415
1489
 
1416
- self.$refs.toolbar.toggleClass("compensate-for-scrollbar", slide.$slide.get(0).scrollHeight > slide.$slide.get(0).clientHeight);
1490
+ if ($slide.length) {
1491
+ $slide.trigger("refresh");
1417
1492
 
1418
- self.trigger("onUpdate", slide);
1493
+ if (slide.pos === self.currPos) {
1494
+ self.$refs.toolbar
1495
+ .add(self.$refs.navigation.find(".fancybox-button--arrow_right"))
1496
+ .toggleClass("compensate-for-scrollbar", $slide.get(0).scrollHeight > $slide.get(0).clientHeight);
1497
+ }
1498
+ }
1499
+
1500
+ self.trigger("onUpdate", slide, e);
1419
1501
  },
1420
1502
 
1421
1503
  // Horizontally center slide
1422
1504
  // =========================
1423
1505
 
1424
- centerSlide: function(slide, duration) {
1506
+ centerSlide: function(duration) {
1425
1507
  var self = this,
1426
- canvasWidth,
1427
- pos;
1508
+ current = self.current,
1509
+ $slide = current.$slide;
1428
1510
 
1429
- if (self.current) {
1430
- canvasWidth = Math.round(slide.$slide.width());
1431
- pos = slide.pos - self.current.pos;
1511
+ if (self.isClosing || !current) {
1512
+ return;
1513
+ }
1432
1514
 
1433
- $.fancybox.animate(
1434
- slide.$slide,
1435
- {
1436
- top: 0,
1437
- left: pos * canvasWidth + pos * slide.opts.gutter,
1438
- opacity: 1
1439
- },
1440
- duration === undefined ? 0 : duration,
1441
- null,
1442
- false
1443
- );
1515
+ $slide.siblings().css({
1516
+ transform: "",
1517
+ opacity: ""
1518
+ });
1519
+
1520
+ $slide
1521
+ .parent()
1522
+ .children()
1523
+ .removeClass("fancybox-slide--previous fancybox-slide--next");
1524
+
1525
+ $.fancybox.animate(
1526
+ $slide,
1527
+ {
1528
+ top: 0,
1529
+ left: 0,
1530
+ opacity: 1
1531
+ },
1532
+ duration === undefined ? 0 : duration,
1533
+ function() {
1534
+ // Clean up
1535
+ $slide.css({
1536
+ transform: "",
1537
+ opacity: ""
1538
+ });
1539
+
1540
+ if (!current.isComplete) {
1541
+ self.complete();
1542
+ }
1543
+ },
1544
+ false
1545
+ );
1546
+ },
1547
+
1548
+ // Check if current slide is moved (swiped)
1549
+ // ========================================
1550
+
1551
+ isMoved: function(slide) {
1552
+ var current = slide || this.current,
1553
+ slidePos,
1554
+ stagePos;
1555
+
1556
+ if (!current) {
1557
+ return false;
1444
1558
  }
1559
+
1560
+ stagePos = $.fancybox.getTranslate(this.$refs.stage);
1561
+ slidePos = $.fancybox.getTranslate(current.$slide);
1562
+
1563
+ return (
1564
+ !current.$slide.hasClass("fancybox-animated") &&
1565
+ (Math.abs(slidePos.top - stagePos.top) > 0.5 || Math.abs(slidePos.left - stagePos.left) > 0.5)
1566
+ );
1445
1567
  },
1446
1568
 
1447
1569
  // Update cursor style depending if content can be zoomed
@@ -1450,38 +1572,33 @@
1450
1572
  updateCursor: function(nextWidth, nextHeight) {
1451
1573
  var self = this,
1452
1574
  current = self.current,
1453
- $container = self.$refs.container.removeClass("fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-drag fancybox-can-zoomOut"),
1575
+ $container = self.$refs.container,
1576
+ canPan,
1454
1577
  isZoomable;
1455
1578
 
1456
- if (!current || self.isClosing) {
1579
+ if (!current || self.isClosing || !self.Guestures) {
1457
1580
  return;
1458
1581
  }
1459
1582
 
1460
- isZoomable = self.isZoomable();
1583
+ $container.removeClass("fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-zoomOut fancybox-can-swipe fancybox-can-pan");
1584
+
1585
+ canPan = self.canPan(nextWidth, nextHeight);
1586
+
1587
+ isZoomable = canPan ? true : self.isZoomable();
1461
1588
 
1462
1589
  $container.toggleClass("fancybox-is-zoomable", isZoomable);
1463
1590
 
1464
1591
  $("[data-fancybox-zoom]").prop("disabled", !isZoomable);
1465
1592
 
1466
- // Set cursor to zoom in/out if click event is 'zoom'
1467
- if (
1593
+ if (canPan) {
1594
+ $container.addClass("fancybox-can-pan");
1595
+ } else if (
1468
1596
  isZoomable &&
1469
- (current.opts.clickContent === "zoom" || ($.isFunction(current.opts.clickContent) && current.opts.clickContent(current) === "zoom"))
1597
+ (current.opts.clickContent === "zoom" || ($.isFunction(current.opts.clickContent) && current.opts.clickContent(current) == "zoom"))
1470
1598
  ) {
1471
- if (self.isScaledDown(nextWidth, nextHeight)) {
1472
- // If image is scaled down, then, obviously, it can be zoomed to full size
1473
- $container.addClass("fancybox-can-zoomIn");
1474
- } else {
1475
- if (current.opts.touch) {
1476
- // If image size ir largen than available available and touch module is not disable,
1477
- // then user can do panning
1478
- $container.addClass("fancybox-can-drag");
1479
- } else {
1480
- $container.addClass("fancybox-can-zoomOut");
1481
- }
1482
- }
1483
- } else if (current.opts.touch && current.contentType !== "video") {
1484
- $container.addClass("fancybox-can-drag");
1599
+ $container.addClass("fancybox-can-zoomIn");
1600
+ } else if (current.opts.touch && (current.opts.touch.vertical || self.group.length > 1) && current.contentType !== "video") {
1601
+ $container.addClass("fancybox-can-swipe");
1485
1602
  }
1486
1603
  },
1487
1604
 
@@ -1503,7 +1620,7 @@
1503
1620
 
1504
1621
  fitPos = self.getFitPos(current);
1505
1622
 
1506
- if (current.width > fitPos.width || current.height > fitPos.height) {
1623
+ if (fitPos && (current.width > fitPos.width || current.height > fitPos.height)) {
1507
1624
  return true;
1508
1625
  }
1509
1626
  }
@@ -1533,15 +1650,24 @@
1533
1650
  // Check if image dimensions exceed parent element
1534
1651
  // ===============================================
1535
1652
 
1536
- canPan: function() {
1653
+ canPan: function(nextWidth, nextHeight) {
1537
1654
  var self = this,
1538
- rez = false,
1539
1655
  current = self.current,
1540
- $content;
1656
+ pos = null,
1657
+ rez = false;
1541
1658
 
1542
- if (current.type === "image" && ($content = current.$content) && !current.hasError) {
1659
+ if (current.type === "image" && (current.isComplete || (nextWidth && nextHeight)) && !current.hasError) {
1543
1660
  rez = self.getFitPos(current);
1544
- rez = Math.abs($content.width() - rez.width) > 1 || Math.abs($content.height() - rez.height) > 1;
1661
+
1662
+ if (nextWidth !== undefined && nextHeight !== undefined) {
1663
+ pos = {width: nextWidth, height: nextHeight};
1664
+ } else if (current.isComplete) {
1665
+ pos = $.fancybox.getTranslate(current.$content);
1666
+ }
1667
+
1668
+ if (pos && rez) {
1669
+ rez = Math.abs(pos.width - rez.width) > 1.5 || Math.abs(pos.height - rez.height) > 1.5;
1670
+ }
1545
1671
  }
1546
1672
 
1547
1673
  return rez;
@@ -1562,7 +1688,11 @@
1562
1688
 
1563
1689
  slide.isLoading = true;
1564
1690
 
1565
- self.trigger("beforeLoad", slide);
1691
+ if (self.trigger("beforeLoad", slide) === false) {
1692
+ slide.isLoading = false;
1693
+
1694
+ return false;
1695
+ }
1566
1696
 
1567
1697
  type = slide.type;
1568
1698
  $slide = slide.$slide;
@@ -1592,14 +1722,10 @@
1592
1722
  case "video":
1593
1723
  self.setContent(
1594
1724
  slide,
1595
- '<video class="fancybox-video" controls controlsList="nodownload">' +
1596
- '<source src="' +
1597
- slide.src +
1598
- '" type="' +
1599
- slide.opts.videoFormat +
1600
- '">' +
1601
- "Your browser doesn't support HTML5 video" +
1602
- "</video"
1725
+ slide.opts.video.tpl
1726
+ .replace(/\{\{src\}\}/gi, slide.src)
1727
+ .replace("{{format}}", slide.opts.videoFormat || slide.opts.video.format || "")
1728
+ .replace("{{poster}}", slide.thumb || "")
1603
1729
  );
1604
1730
 
1605
1731
  break;
@@ -1652,21 +1778,61 @@
1652
1778
 
1653
1779
  setImage: function(slide) {
1654
1780
  var self = this,
1655
- srcset = slide.opts.srcset || slide.opts.image.srcset,
1656
- thumbSrc,
1657
- found,
1658
- temp,
1659
- pxRatio,
1660
- windowWidth;
1781
+ ghost;
1661
1782
 
1662
1783
  // Check if need to show loading icon
1663
- slide.timouts = setTimeout(function() {
1784
+ setTimeout(function() {
1664
1785
  var $img = slide.$image;
1665
1786
 
1666
- if (slide.isLoading && (!$img || !$img[0].complete) && !slide.hasError) {
1787
+ if (!self.isClosing && slide.isLoading && (!$img || !$img.length || !$img[0].complete) && !slide.hasError) {
1667
1788
  self.showLoading(slide);
1668
1789
  }
1669
- }, 350);
1790
+ }, 50);
1791
+
1792
+ //Check if image has srcset
1793
+ self.checkSrcset(slide);
1794
+
1795
+ // This will be wrapper containing both ghost and actual image
1796
+ slide.$content = $('<div class="fancybox-content"></div>')
1797
+ .addClass("fancybox-is-hidden")
1798
+ .appendTo(slide.$slide.addClass("fancybox-slide--image"));
1799
+
1800
+ // If we have a thumbnail, we can display it while actual image is loading
1801
+ // Users will not stare at black screen and actual image will appear gradually
1802
+ if (slide.opts.preload !== false && slide.opts.width && slide.opts.height && slide.thumb) {
1803
+ slide.width = slide.opts.width;
1804
+ slide.height = slide.opts.height;
1805
+
1806
+ ghost = document.createElement("img");
1807
+
1808
+ ghost.onerror = function() {
1809
+ $(this).remove();
1810
+
1811
+ slide.$ghost = null;
1812
+ };
1813
+
1814
+ ghost.onload = function() {
1815
+ self.afterLoad(slide);
1816
+ };
1817
+
1818
+ slide.$ghost = $(ghost)
1819
+ .addClass("fancybox-image")
1820
+ .appendTo(slide.$content)
1821
+ .attr("src", slide.thumb);
1822
+ }
1823
+
1824
+ // Start loading actual image
1825
+ self.setBigImage(slide);
1826
+ },
1827
+
1828
+ // Check if image has srcset and get the source
1829
+ // ============================================
1830
+ checkSrcset: function(slide) {
1831
+ var srcset = slide.opts.srcset || slide.opts.image.srcset,
1832
+ found,
1833
+ temp,
1834
+ pxRatio,
1835
+ windowWidth;
1670
1836
 
1671
1837
  // If we have "srcset", then we need to find first matching "src" value.
1672
1838
  // This is necessary, because when you set an src attribute, the browser will preload the image
@@ -1678,8 +1844,7 @@
1678
1844
  temp = srcset.split(",").map(function(el) {
1679
1845
  var ret = {};
1680
1846
 
1681
- el
1682
- .trim()
1847
+ el.trim()
1683
1848
  .split(/\s+/)
1684
1849
  .forEach(function(el, i) {
1685
1850
  var value = parseInt(el.substring(0, el.length - 1), 10);
@@ -1722,43 +1887,13 @@
1722
1887
 
1723
1888
  // If we have default width/height values, we can calculate height for matching source
1724
1889
  if (slide.width && slide.height && found.postfix == "w") {
1725
- slide.height = slide.width / slide.height * found.value;
1890
+ slide.height = (slide.width / slide.height) * found.value;
1726
1891
  slide.width = found.value;
1727
1892
  }
1728
1893
 
1729
1894
  slide.opts.srcset = srcset;
1730
1895
  }
1731
1896
  }
1732
-
1733
- // This will be wrapper containing both ghost and actual image
1734
- slide.$content = $('<div class="fancybox-content"></div>')
1735
- .addClass("fancybox-is-hidden")
1736
- .appendTo(slide.$slide.addClass("fancybox-slide--image"));
1737
-
1738
- // If we have a thumbnail, we can display it while actual image is loading
1739
- // Users will not stare at black screen and actual image will appear gradually
1740
- thumbSrc = slide.opts.thumb || (slide.opts.$thumb && slide.opts.$thumb.length ? slide.opts.$thumb.attr("src") : false);
1741
-
1742
- if (slide.opts.preload !== false && slide.opts.width && slide.opts.height && thumbSrc) {
1743
- slide.width = slide.opts.width;
1744
- slide.height = slide.opts.height;
1745
-
1746
- slide.$ghost = $("<img />")
1747
- .one("error", function() {
1748
- $(this).remove();
1749
-
1750
- slide.$ghost = null;
1751
- })
1752
- .one("load", function() {
1753
- self.afterLoad(slide);
1754
- })
1755
- .addClass("fancybox-image")
1756
- .appendTo(slide.$content)
1757
- .attr("src", thumbSrc);
1758
- }
1759
-
1760
- // Start loading actual image
1761
- self.setBigImage(slide);
1762
1897
  },
1763
1898
 
1764
1899
  // Create full-size image
@@ -1766,7 +1901,8 @@
1766
1901
 
1767
1902
  setBigImage: function(slide) {
1768
1903
  var self = this,
1769
- $img = $("<img />");
1904
+ img = document.createElement("img"),
1905
+ $img = $(img);
1770
1906
 
1771
1907
  slide.$image = $img
1772
1908
  .one("error", function() {
@@ -1781,12 +1917,6 @@
1781
1917
  self.afterLoad(slide);
1782
1918
  }
1783
1919
 
1784
- // Clear timeout that checks if loading icon needs to be displayed
1785
- if (slide.timouts) {
1786
- clearTimeout(slide.timouts);
1787
- slide.timouts = null;
1788
- }
1789
-
1790
1920
  if (self.isClosing) {
1791
1921
  return;
1792
1922
  }
@@ -1796,7 +1926,7 @@
1796
1926
 
1797
1927
  if (!sizes || sizes === "auto") {
1798
1928
  sizes =
1799
- (slide.width / slide.height > 1 && $W.width() / $W.height() > 1 ? "100" : Math.round(slide.width / slide.height * 100)) +
1929
+ (slide.width / slide.height > 1 && $W.width() / $W.height() > 1 ? "100" : Math.round((slide.width / slide.height) * 100)) +
1800
1930
  "vw";
1801
1931
  }
1802
1932
 
@@ -1818,9 +1948,9 @@
1818
1948
  .attr("src", slide.src)
1819
1949
  .appendTo(slide.$content);
1820
1950
 
1821
- if (($img[0].complete || $img[0].readyState == "complete") && $img[0].naturalWidth && $img[0].naturalHeight) {
1951
+ if ((img.complete || img.readyState == "complete") && $img.naturalWidth && $img.naturalHeight) {
1822
1952
  $img.trigger("load");
1823
- } else if ($img[0].error) {
1953
+ } else if (img.error) {
1824
1954
  $img.trigger("error");
1825
1955
  }
1826
1956
  },
@@ -1838,11 +1968,11 @@
1838
1968
 
1839
1969
  if (maxWidth > 0) {
1840
1970
  slide.width = maxWidth;
1841
- slide.height = Math.floor(maxWidth * imgHeight / imgWidth);
1971
+ slide.height = Math.floor((maxWidth * imgHeight) / imgWidth);
1842
1972
  }
1843
1973
 
1844
1974
  if (maxHeight > 0) {
1845
- slide.width = Math.floor(maxHeight * imgWidth / imgHeight);
1975
+ slide.width = Math.floor((maxHeight * imgWidth) / imgHeight);
1846
1976
  slide.height = maxHeight;
1847
1977
  }
1848
1978
  },
@@ -1856,6 +1986,11 @@
1856
1986
  $slide = slide.$slide,
1857
1987
  $iframe;
1858
1988
 
1989
+ // Fix responsive iframes on iOS (along with `position:absolute;` for iframe element)
1990
+ if ($.fancybox.isMobile) {
1991
+ opts.css.overflow = "scroll";
1992
+ }
1993
+
1859
1994
  slide.$content = $('<div class="fancybox-content' + (opts.preload ? " fancybox-is-hidden" : "") + '"></div>')
1860
1995
  .css(opts.css)
1861
1996
  .appendTo($slide);
@@ -1901,32 +2036,34 @@
1901
2036
 
1902
2037
  // Calculate contnet dimensions if it is accessible
1903
2038
  if ($body && $body.length && $body.children().length) {
2039
+ // Avoid scrolling to top (if multiple instances)
2040
+ $slide.css("overflow", "visible");
2041
+
1904
2042
  $content.css({
1905
- width: "",
1906
- height: ""
2043
+ width: "100%",
2044
+ "max-width": "100%",
2045
+ height: "9999px"
1907
2046
  });
1908
2047
 
1909
2048
  if (frameWidth === undefined) {
1910
2049
  frameWidth = Math.ceil(Math.max($body[0].clientWidth, $body.outerWidth(true)));
1911
2050
  }
1912
2051
 
1913
- if (frameWidth) {
1914
- $content.width(frameWidth);
1915
- }
2052
+ $content.css("width", frameWidth ? frameWidth : "").css("max-width", "");
1916
2053
 
1917
2054
  if (frameHeight === undefined) {
1918
2055
  frameHeight = Math.ceil(Math.max($body[0].clientHeight, $body.outerHeight(true)));
1919
2056
  }
1920
2057
 
1921
- if (frameHeight) {
1922
- $content.height(frameHeight);
1923
- }
2058
+ $content.css("height", frameHeight ? frameHeight : "");
2059
+
2060
+ $slide.css("overflow", "auto");
1924
2061
  }
1925
2062
 
1926
2063
  $content.removeClass("fancybox-is-hidden");
1927
2064
  });
1928
2065
  } else {
1929
- this.afterLoad(slide);
2066
+ self.afterLoad(slide);
1930
2067
  }
1931
2068
 
1932
2069
  $iframe.attr("src", slide.src);
@@ -1947,6 +2084,7 @@
1947
2084
  .empty();
1948
2085
 
1949
2086
  slide.isLoaded = false;
2087
+ slide.isRevealed = false;
1950
2088
  });
1951
2089
  },
1952
2090
 
@@ -1972,10 +2110,9 @@
1972
2110
  // The placeholder is created so we will know where to put it back.
1973
2111
  if (isQuery(content) && content.parent().length) {
1974
2112
  // Make sure content is not already moved to fancyBox
1975
- content
1976
- .parent()
1977
- .parent(".fancybox-slide--inline")
1978
- .trigger("onReset");
2113
+ if (content.hasClass("fancybox-content") || content.parent().hasClass("fancybox-content")) {
2114
+ content.parents(".fancybox-slide").trigger("onReset");
2115
+ }
1979
2116
 
1980
2117
  // Create temporary element marking original place of the content
1981
2118
  slide.$placeholder = $("<div>")
@@ -1990,11 +2127,6 @@
1990
2127
  content = $("<div>")
1991
2128
  .append($.trim(content))
1992
2129
  .contents();
1993
-
1994
- // If we have text node, then add wrapping element to make vertical alignment work
1995
- if (content[0].nodeType === 3) {
1996
- content = $("<div>").html(content);
1997
- }
1998
2130
  }
1999
2131
 
2000
2132
  // If "filter" option is provided, then filter content
@@ -2013,7 +2145,7 @@
2013
2145
 
2014
2146
  // Put content back
2015
2147
  if (slide.$placeholder) {
2016
- slide.$placeholder.after(content.hide()).remove();
2148
+ slide.$placeholder.after(content.removeClass("fancybox-content").hide()).remove();
2017
2149
 
2018
2150
  slide.$placeholder = null;
2019
2151
  }
@@ -2030,6 +2162,7 @@
2030
2162
  $(this).empty();
2031
2163
 
2032
2164
  slide.isLoaded = false;
2165
+ slide.isRevealed = false;
2033
2166
  }
2034
2167
  });
2035
2168
 
@@ -2048,13 +2181,25 @@
2048
2181
 
2049
2182
  slide.$content = slide.$slide
2050
2183
  .children()
2051
- .filter("div,form,main,video,audio")
2052
- .first()
2053
- .addClass("fancybox-content");
2184
+ .filter("div,form,main,video,audio,article,.fancybox-content")
2185
+ .first();
2186
+
2187
+ slide.$content.siblings().hide();
2188
+
2189
+ // Re-check if there is a valid content
2190
+ // (in some cases, ajax response can contain various elements or plain text)
2191
+ if (!slide.$content.length) {
2192
+ slide.$content = slide.$slide
2193
+ .wrapInner("<div></div>")
2194
+ .children()
2195
+ .first();
2196
+ }
2197
+
2198
+ slide.$content.addClass("fancybox-content");
2054
2199
 
2055
2200
  slide.$slide.addClass("fancybox-slide--" + slide.contentType);
2056
2201
 
2057
- this.afterLoad(slide);
2202
+ self.afterLoad(slide);
2058
2203
  },
2059
2204
 
2060
2205
  // Display error message
@@ -2086,7 +2231,10 @@
2086
2231
  slide = slide || self.current;
2087
2232
 
2088
2233
  if (slide && !slide.$spinner) {
2089
- slide.$spinner = $(self.translate(self, self.opts.spinnerTpl)).appendTo(slide.$slide);
2234
+ slide.$spinner = $(self.translate(self, self.opts.spinnerTpl))
2235
+ .appendTo(slide.$slide)
2236
+ .hide()
2237
+ .fadeIn("fast");
2090
2238
  }
2091
2239
  },
2092
2240
 
@@ -2099,7 +2247,7 @@
2099
2247
  slide = slide || self.current;
2100
2248
 
2101
2249
  if (slide && slide.$spinner) {
2102
- slide.$spinner.remove();
2250
+ slide.$spinner.stop().remove();
2103
2251
 
2104
2252
  delete slide.$spinner;
2105
2253
  }
@@ -2122,16 +2270,13 @@
2122
2270
 
2123
2271
  self.hideLoading(slide);
2124
2272
 
2125
- if (slide.pos === self.currPos) {
2126
- self.updateCursor();
2127
- }
2128
-
2273
+ // Add small close button
2129
2274
  if (slide.opts.smallBtn && (!slide.$smallBtn || !slide.$smallBtn.length)) {
2130
- slide.$smallBtn = $(self.translate(slide, slide.opts.btnTpl.smallBtn)).prependTo(slide.$content);
2275
+ slide.$smallBtn = $(self.translate(slide, slide.opts.btnTpl.smallBtn)).appendTo(slide.$content);
2131
2276
  }
2132
2277
 
2278
+ // Disable right click
2133
2279
  if (slide.opts.protect && slide.$content && !slide.hasError) {
2134
- // Disable right click
2135
2280
  slide.$content.on("contextmenu.fb", function(e) {
2136
2281
  if (e.button == 2) {
2137
2282
  e.preventDefault();
@@ -2147,9 +2292,86 @@
2147
2292
  }
2148
2293
  }
2149
2294
 
2295
+ self.adjustCaption(slide);
2296
+
2297
+ self.adjustLayout(slide);
2298
+
2299
+ if (slide.pos === self.currPos) {
2300
+ self.updateCursor();
2301
+ }
2302
+
2150
2303
  self.revealContent(slide);
2151
2304
  },
2152
2305
 
2306
+ // Prevent caption overlap,
2307
+ // fix css inconsistency across browsers
2308
+ // =====================================
2309
+
2310
+ adjustCaption: function(slide) {
2311
+ var self = this,
2312
+ current = slide || self.current,
2313
+ caption = current.opts.caption,
2314
+ $caption = self.$refs.caption,
2315
+ captionH = false;
2316
+
2317
+ if (current.opts.preventCaptionOverlap && caption && caption.length) {
2318
+ if (current.pos !== self.currPos) {
2319
+ $caption = $caption
2320
+ .clone()
2321
+ .empty()
2322
+ .appendTo($caption.parent());
2323
+
2324
+ $caption.html(caption);
2325
+
2326
+ captionH = $caption.outerHeight(true);
2327
+
2328
+ $caption.empty().remove();
2329
+ } else if (self.$caption) {
2330
+ captionH = self.$caption.outerHeight(true);
2331
+ }
2332
+
2333
+ current.$slide.css("padding-bottom", captionH || "");
2334
+ }
2335
+ },
2336
+
2337
+ // Simple hack to fix inconsistency across browsers, described here (affects Edge, too):
2338
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=748518
2339
+ // ====================================================================================
2340
+
2341
+ adjustLayout: function(slide) {
2342
+ var self = this,
2343
+ current = slide || self.current,
2344
+ scrollHeight,
2345
+ marginBottom,
2346
+ inlinePadding,
2347
+ actualPadding;
2348
+
2349
+ if (current.isLoaded && current.opts.disableLayoutFix !== true) {
2350
+ current.$content.css("margin-bottom", "");
2351
+
2352
+ // If we would always set margin-bottom for the content,
2353
+ // then it would potentially break vertical align
2354
+ if (current.$content.outerHeight() > current.$slide.height() + 0.5) {
2355
+ inlinePadding = current.$slide[0].style["padding-bottom"];
2356
+ actualPadding = current.$slide.css("padding-bottom");
2357
+
2358
+ if (parseFloat(actualPadding) > 0) {
2359
+ scrollHeight = current.$slide[0].scrollHeight;
2360
+
2361
+ current.$slide.css("padding-bottom", 0);
2362
+
2363
+ if (Math.abs(scrollHeight - current.$slide[0].scrollHeight) < 1) {
2364
+ marginBottom = actualPadding;
2365
+ }
2366
+
2367
+ current.$slide.css("padding-bottom", inlinePadding);
2368
+ }
2369
+ }
2370
+
2371
+ current.$content.css("margin-bottom", marginBottom);
2372
+ }
2373
+ },
2374
+
2153
2375
  // Make content visible
2154
2376
  // This method is called right after content has been loaded or
2155
2377
  // user navigates gallery and transition should start
@@ -2160,26 +2382,21 @@
2160
2382
  $slide = slide.$slide,
2161
2383
  end = false,
2162
2384
  start = false,
2385
+ isMoved = self.isMoved(slide),
2386
+ isRevealed = slide.isRevealed,
2163
2387
  effect,
2164
2388
  effectClassName,
2165
2389
  duration,
2166
2390
  opacity;
2167
2391
 
2392
+ slide.isRevealed = true;
2393
+
2168
2394
  effect = slide.opts[self.firstRun ? "animationEffect" : "transitionEffect"];
2169
2395
  duration = slide.opts[self.firstRun ? "animationDuration" : "transitionDuration"];
2170
2396
 
2171
2397
  duration = parseInt(slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10);
2172
2398
 
2173
- // Do not animate if revealing the same slide
2174
- if (slide.pos === self.currPos) {
2175
- if (slide.isComplete) {
2176
- effect = false;
2177
- } else {
2178
- self.isAnimating = true;
2179
- }
2180
- }
2181
-
2182
- if (slide.isMoved || slide.pos !== self.currPos || !duration) {
2399
+ if (isMoved || slide.pos !== self.currPos || !duration) {
2183
2400
  effect = false;
2184
2401
  }
2185
2402
 
@@ -2195,6 +2412,8 @@
2195
2412
  // Zoom animation
2196
2413
  // ==============
2197
2414
  if (effect === "zoom") {
2415
+ self.isAnimating = true;
2416
+
2198
2417
  end.scaleX = end.width / start.width;
2199
2418
  end.scaleY = end.height / start.height;
2200
2419
 
@@ -2227,14 +2446,15 @@
2227
2446
 
2228
2447
  self.updateSlide(slide);
2229
2448
 
2230
- // Simply show content
2231
- // ===================
2232
-
2449
+ // Simply show content if no effect
2450
+ // ================================
2233
2451
  if (!effect) {
2234
- forceRedraw($slide);
2235
-
2236
2452
  slide.$content.removeClass("fancybox-is-hidden");
2237
2453
 
2454
+ if (!isRevealed && isMoved && slide.type === "image" && !slide.hasError) {
2455
+ slide.$content.hide().fadeIn("fast");
2456
+ }
2457
+
2238
2458
  if (slide.pos === self.currPos) {
2239
2459
  self.complete();
2240
2460
  }
@@ -2242,26 +2462,33 @@
2242
2462
  return;
2243
2463
  }
2244
2464
 
2465
+ // Prepare for CSS transiton
2466
+ // =========================
2245
2467
  $.fancybox.stop($slide);
2246
2468
 
2247
- effectClassName = "fancybox-animated fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-fx-" + effect;
2469
+ //effectClassName = "fancybox-animated fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-fx-" + effect;
2470
+ effectClassName = "fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-animated fancybox-fx-" + effect;
2248
2471
 
2249
- $slide
2250
- .removeAttr("style")
2251
- .removeClass("fancybox-slide--current fancybox-slide--next fancybox-slide--previous")
2252
- .addClass(effectClassName);
2472
+ $slide.addClass(effectClassName).removeClass("fancybox-slide--current"); //.addClass(effectClassName);
2253
2473
 
2254
2474
  slide.$content.removeClass("fancybox-is-hidden");
2255
2475
 
2256
- // Force reflow for CSS3 transitions
2476
+ // Force reflow
2257
2477
  forceRedraw($slide);
2258
2478
 
2479
+ if (slide.type !== "image") {
2480
+ slide.$content.hide().show(0);
2481
+ }
2482
+
2259
2483
  $.fancybox.animate(
2260
2484
  $slide,
2261
2485
  "fancybox-slide--current",
2262
2486
  duration,
2263
- function(e) {
2264
- $slide.removeClass(effectClassName).removeAttr("style");
2487
+ function() {
2488
+ $slide.removeClass(effectClassName).css({
2489
+ transform: "",
2490
+ opacity: ""
2491
+ });
2265
2492
 
2266
2493
  if (slide.pos === self.currPos) {
2267
2494
  self.complete();
@@ -2275,57 +2502,35 @@
2275
2502
  //================================================
2276
2503
 
2277
2504
  getThumbPos: function(slide) {
2278
- var self = this,
2279
- rez = false,
2280
- $thumb = slide.opts.$thumb,
2281
- thumbPos = $thumb && $thumb.length && $thumb[0].ownerDocument === document ? $thumb.offset() : 0,
2282
- slidePos;
2283
-
2284
- // Check if element is inside the viewport by at least 1 pixel
2285
- var isElementVisible = function($el) {
2286
- var element = $el[0],
2287
- elementRect = element.getBoundingClientRect(),
2288
- parentRects = [],
2289
- visibleInAllParents;
2290
-
2291
- while (element.parentElement !== null) {
2292
- if ($(element.parentElement).css("overflow") === "hidden" || $(element.parentElement).css("overflow") === "auto") {
2293
- parentRects.push(element.parentElement.getBoundingClientRect());
2294
- }
2295
-
2296
- element = element.parentElement;
2297
- }
2505
+ var rez = false,
2506
+ $thumb = slide.$thumb,
2507
+ thumbPos,
2508
+ btw,
2509
+ brw,
2510
+ bbw,
2511
+ blw;
2512
+
2513
+ if (!$thumb || !inViewport($thumb[0])) {
2514
+ return false;
2515
+ }
2298
2516
 
2299
- visibleInAllParents = parentRects.every(function(parentRect) {
2300
- var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
2301
- var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
2517
+ thumbPos = $.fancybox.getTranslate($thumb);
2302
2518
 
2303
- return visiblePixelX > 0 && visiblePixelY > 0;
2304
- });
2519
+ btw = parseFloat($thumb.css("border-top-width") || 0);
2520
+ brw = parseFloat($thumb.css("border-right-width") || 0);
2521
+ bbw = parseFloat($thumb.css("border-bottom-width") || 0);
2522
+ blw = parseFloat($thumb.css("border-left-width") || 0);
2305
2523
 
2306
- return (
2307
- visibleInAllParents &&
2308
- elementRect.bottom > 0 &&
2309
- elementRect.right > 0 &&
2310
- elementRect.left < $(window).width() &&
2311
- elementRect.top < $(window).height()
2312
- );
2524
+ rez = {
2525
+ top: thumbPos.top + btw,
2526
+ left: thumbPos.left + blw,
2527
+ width: thumbPos.width - brw - blw,
2528
+ height: thumbPos.height - btw - bbw,
2529
+ scaleX: 1,
2530
+ scaleY: 1
2313
2531
  };
2314
2532
 
2315
- if (thumbPos && isElementVisible($thumb)) {
2316
- slidePos = self.$refs.stage.offset();
2317
-
2318
- rez = {
2319
- top: thumbPos.top - slidePos.top + parseFloat($thumb.css("border-top-width") || 0),
2320
- left: thumbPos.left - slidePos.left + parseFloat($thumb.css("border-left-width") || 0),
2321
- width: $thumb.width(),
2322
- height: $thumb.height(),
2323
- scaleX: 1,
2324
- scaleY: 1
2325
- };
2326
- }
2327
-
2328
- return rez;
2533
+ return thumbPos.width > 0 && thumbPos.height > 0 ? rez : false;
2329
2534
  },
2330
2535
 
2331
2536
  // Final adjustments after current gallery item is moved to position
@@ -2335,9 +2540,10 @@
2335
2540
  complete: function() {
2336
2541
  var self = this,
2337
2542
  current = self.current,
2338
- slides = {};
2543
+ slides = {},
2544
+ $el;
2339
2545
 
2340
- if (current.isMoved || !current.isLoaded) {
2546
+ if (self.isMoved() || !current.isLoaded) {
2341
2547
  return;
2342
2548
  }
2343
2549
 
@@ -2348,7 +2554,7 @@
2348
2554
 
2349
2555
  self.preload("inline");
2350
2556
 
2351
- // Trigger any CSS3 transiton inside the slide
2557
+ // Trigger any CSS transiton inside the slide
2352
2558
  forceRedraw(current.$slide);
2353
2559
 
2354
2560
  current.$slide.addClass("fancybox-slide--complete");
@@ -2373,19 +2579,35 @@
2373
2579
 
2374
2580
  self.trigger("afterShow");
2375
2581
 
2376
- // Play first html5 video/audio
2377
- current.$slide
2378
- .find("video,audio")
2379
- .filter(":visible:first")
2380
- .trigger("play");
2582
+ // Autoplay first html5 video/audio
2583
+ if (!!current.opts.video.autoStart) {
2584
+ current.$slide
2585
+ .find("video,audio")
2586
+ .filter(":visible:first")
2587
+ .trigger("play")
2588
+ .one("ended", function() {
2589
+ if (this.webkitExitFullscreen) {
2590
+ this.webkitExitFullscreen();
2591
+ }
2592
+
2593
+ self.next();
2594
+ });
2595
+ }
2381
2596
 
2382
2597
  // Try to focus on the first focusable element
2383
- if (
2384
- $(document.activeElement).is("[disabled]") ||
2385
- (current.opts.autoFocus && !(current.type == "image" || current.type === "iframe"))
2386
- ) {
2387
- self.focus();
2598
+ if (current.opts.autoFocus && current.contentType === "html") {
2599
+ // Look for the first input with autofocus attribute
2600
+ $el = current.$content.find("input[autofocus]:enabled:visible:first");
2601
+
2602
+ if ($el.length) {
2603
+ $el.trigger("focus");
2604
+ } else {
2605
+ self.focus(null, true);
2606
+ }
2388
2607
  }
2608
+
2609
+ // Avoid jumping
2610
+ current.$slide.scrollTop(0).scrollLeft(0);
2389
2611
  },
2390
2612
 
2391
2613
  // Preload next and previous slides
@@ -2393,40 +2615,84 @@
2393
2615
 
2394
2616
  preload: function(type) {
2395
2617
  var self = this,
2396
- next = self.slides[self.currPos + 1],
2397
- prev = self.slides[self.currPos - 1];
2618
+ prev,
2619
+ next;
2398
2620
 
2399
- if (next && next.type === type) {
2400
- self.loadSlide(next);
2621
+ if (self.group.length < 2) {
2622
+ return;
2401
2623
  }
2402
2624
 
2625
+ next = self.slides[self.currPos + 1];
2626
+ prev = self.slides[self.currPos - 1];
2627
+
2403
2628
  if (prev && prev.type === type) {
2404
2629
  self.loadSlide(prev);
2405
2630
  }
2631
+
2632
+ if (next && next.type === type) {
2633
+ self.loadSlide(next);
2634
+ }
2406
2635
  },
2407
2636
 
2408
2637
  // Try to find and focus on the first focusable element
2409
2638
  // ====================================================
2410
2639
 
2411
- focus: function() {
2412
- var current = this.current,
2413
- $el;
2640
+ focus: function(e, firstRun) {
2641
+ var self = this,
2642
+ focusableStr = [
2643
+ "a[href]",
2644
+ "area[href]",
2645
+ 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
2646
+ "select:not([disabled]):not([aria-hidden])",
2647
+ "textarea:not([disabled]):not([aria-hidden])",
2648
+ "button:not([disabled]):not([aria-hidden])",
2649
+ "iframe",
2650
+ "object",
2651
+ "embed",
2652
+ "[contenteditable]",
2653
+ '[tabindex]:not([tabindex^="-"])'
2654
+ ].join(","),
2655
+ focusableItems,
2656
+ focusedItemIndex;
2414
2657
 
2415
- if (this.isClosing) {
2658
+ if (self.isClosing) {
2416
2659
  return;
2417
2660
  }
2418
2661
 
2419
- if (current && current.isComplete && current.$content) {
2420
- // Look for first input with autofocus attribute
2421
- $el = current.$content.find("input[autofocus]:enabled:visible:first");
2662
+ if (e || !self.current || !self.current.isComplete) {
2663
+ // Focus on any element inside fancybox
2664
+ focusableItems = self.$refs.container.find("*:visible");
2665
+ } else {
2666
+ // Focus inside current slide
2667
+ focusableItems = self.current.$slide.find("*:visible" + (firstRun ? ":not(.fancybox-close-small)" : ""));
2668
+ }
2422
2669
 
2423
- if (!$el.length) {
2424
- $el = current.$content.find("button,:input,[tabindex],a").filter(":enabled:visible:first");
2425
- }
2670
+ focusableItems = focusableItems.filter(focusableStr).filter(function() {
2671
+ return $(this).css("visibility") !== "hidden" && !$(this).hasClass("disabled");
2672
+ });
2673
+
2674
+ if (focusableItems.length) {
2675
+ focusedItemIndex = focusableItems.index(document.activeElement);
2676
+
2677
+ if (e && e.shiftKey) {
2678
+ // Back tab
2679
+ if (focusedItemIndex < 0 || focusedItemIndex == 0) {
2680
+ e.preventDefault();
2426
2681
 
2427
- $el = $el && $el.length ? $el : current.$content;
2682
+ focusableItems.eq(focusableItems.length - 1).trigger("focus");
2683
+ }
2684
+ } else {
2685
+ // Outside or Forward tab
2686
+ if (focusedItemIndex < 0 || focusedItemIndex == focusableItems.length - 1) {
2687
+ if (e) {
2688
+ e.preventDefault();
2689
+ }
2428
2690
 
2429
- $el.trigger("focus");
2691
+ focusableItems.eq(0).trigger("focus");
2692
+ }
2693
+ }
2694
+ } else {
2695
+ self.$refs.container.trigger("focus");
2430
2696
  }
2431
2697
  },
2432
2698
 
@@ -2504,19 +2770,19 @@
2504
2770
  // If there are multiple instances, they will be set again by "activate" method
2505
2771
  self.removeEvents();
2506
2772
 
2507
- if (current.timouts) {
2508
- clearTimeout(current.timouts);
2509
- }
2510
-
2511
2773
  $content = current.$content;
2512
2774
  effect = current.opts.animationEffect;
2513
2775
  duration = $.isNumeric(d) ? d : effect ? current.opts.animationDuration : 0;
2514
2776
 
2515
- // Remove other slides
2516
- current.$slide
2517
- .off(transitionEnd)
2518
- .removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated");
2777
+ current.$slide.removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated");
2778
+
2779
+ if (e !== true) {
2780
+ $.fancybox.stop(current.$slide);
2781
+ } else {
2782
+ effect = false;
2783
+ }
2519
2784
 
2785
+ // Remove other slides
2520
2786
  current.$slide
2521
2787
  .siblings()
2522
2788
  .trigger("onReset")
@@ -2524,20 +2790,23 @@
2524
2790
 
2525
2791
  // Trigger animations
2526
2792
  if (duration) {
2527
- self.$refs.container.removeClass("fancybox-is-open").addClass("fancybox-is-closing");
2793
+ self.$refs.container
2794
+ .removeClass("fancybox-is-open")
2795
+ .addClass("fancybox-is-closing")
2796
+ .css("transition-duration", duration + "ms");
2528
2797
  }
2529
2798
 
2530
2799
  // Clean up
2531
2800
  self.hideLoading(current);
2532
2801
 
2533
- self.hideControls();
2802
+ self.hideControls(true);
2534
2803
 
2535
2804
  self.updateCursor();
2536
2805
 
2537
2806
  // Check if possible to zoom-out
2538
2807
  if (
2539
2808
  effect === "zoom" &&
2540
- !(e !== true && $content && duration && current.type === "image" && !current.hasError && (end = self.getThumbPos(current)))
2809
+ !($content && duration && current.type === "image" && !self.isMoved() && !current.hasError && (end = self.getThumbPos(current)))
2541
2810
  ) {
2542
2811
  effect = "fade";
2543
2812
  }
@@ -2577,19 +2846,19 @@
2577
2846
  }
2578
2847
 
2579
2848
  if (effect && duration) {
2849
+ $.fancybox.animate(
2850
+ current.$slide.addClass("fancybox-slide--previous").removeClass("fancybox-slide--current"),
2851
+ "fancybox-animated fancybox-fx-" + effect,
2852
+ duration,
2853
+ done
2854
+ );
2855
+ } else {
2580
2856
  // If skip animation
2581
2857
  if (e === true) {
2582
2858
  setTimeout(done, duration);
2583
2859
  } else {
2584
- $.fancybox.animate(
2585
- current.$slide.removeClass("fancybox-slide--current"),
2586
- "fancybox-animated fancybox-slide--previous fancybox-fx-" + effect,
2587
- duration,
2588
- done
2589
- );
2860
+ done();
2590
2861
  }
2591
- } else {
2592
- done();
2593
2862
  }
2594
2863
 
2595
2864
  return true;
@@ -2600,9 +2869,10 @@
2600
2869
 
2601
2870
  cleanUp: function(e) {
2602
2871
  var self = this,
2603
- $body = $("body"),
2604
2872
  instance,
2605
- scrollTop;
2873
+ $focus = self.current.opts.$orig,
2874
+ x,
2875
+ y;
2606
2876
 
2607
2877
  self.current.$slide.trigger("onReset");
2608
2878
 
@@ -2611,8 +2881,21 @@
2611
2881
  self.trigger("afterClose", e);
2612
2882
 
2613
2883
  // Place back focus
2614
- if (self.$lastFocus && !!self.current.opts.backFocus) {
2615
- self.$lastFocus.trigger("focus");
2884
+ if (!!self.current.opts.backFocus) {
2885
+ if (!$focus || !$focus.length || !$focus.is(":visible")) {
2886
+ $focus = self.$trigger;
2887
+ }
2888
+
2889
+ if ($focus && $focus.length) {
2890
+ x = window.scrollX;
2891
+ y = window.scrollY;
2892
+
2893
+ $focus.trigger("focus");
2894
+
2895
+ $("html, body")
2896
+ .scrollTop(y)
2897
+ .scrollLeft(x);
2898
+ }
2616
2899
  }
2617
2900
 
2618
2901
  self.current = null;
@@ -2623,7 +2906,7 @@
2623
2906
  if (instance) {
2624
2907
  instance.activate();
2625
2908
  } else {
2626
- $body.removeClass("fancybox-active compensate-for-scrollbar");
2909
+ $("body").removeClass("fancybox-active compensate-for-scrollbar");
2627
2910
 
2628
2911
  $("#fancybox-style-noscroll").remove();
2629
2912
  }
@@ -2664,20 +2947,20 @@
2664
2947
  // Update infobar values, navigation button states and reveal caption
2665
2948
  // ==================================================================
2666
2949
 
2667
- updateControls: function(force) {
2950
+ updateControls: function() {
2668
2951
  var self = this,
2669
2952
  current = self.current,
2670
2953
  index = current.index,
2671
- caption = current.opts.caption,
2672
2954
  $container = self.$refs.container,
2673
- $caption = self.$refs.caption;
2955
+ $caption = self.$refs.caption,
2956
+ caption = current.opts.caption;
2674
2957
 
2675
2958
  // Recalculate content dimensions
2676
2959
  current.$slide.trigger("refresh");
2677
2960
 
2678
2961
  self.$caption = caption && caption.length ? $caption.html(caption) : null;
2679
2962
 
2680
- if (!self.isHiddenControls && !self.isIdle) {
2963
+ if (!self.hasHiddenControls && !self.isIdle) {
2681
2964
  self.showControls();
2682
2965
  }
2683
2966
 
@@ -2685,8 +2968,8 @@
2685
2968
  $container.find("[data-fancybox-count]").html(self.group.length);
2686
2969
  $container.find("[data-fancybox-index]").html(index + 1);
2687
2970
 
2688
- $container.find("[data-fancybox-prev]").toggleClass("disabled", !current.opts.loop && index <= 0);
2689
- $container.find("[data-fancybox-next]").toggleClass("disabled", !current.opts.loop && index >= self.group.length - 1);
2971
+ $container.find("[data-fancybox-prev]").prop("disabled", !current.opts.loop && index <= 0);
2972
+ $container.find("[data-fancybox-next]").prop("disabled", !current.opts.loop && index >= self.group.length - 1);
2690
2973
 
2691
2974
  if (current.type === "image") {
2692
2975
  // Re-enable buttons; update download button source
@@ -2700,15 +2983,33 @@
2700
2983
  } else if (current.opts.toolbar) {
2701
2984
  $container.find("[data-fancybox-download],[data-fancybox-zoom]").hide();
2702
2985
  }
2986
+
2987
+ // Make sure focus is not on disabled button/element
2988
+ if ($(document.activeElement).is(":hidden,[disabled]")) {
2989
+ self.$refs.container.trigger("focus");
2990
+ }
2703
2991
  },
2704
2992
 
2705
2993
  // Hide toolbar and caption
2706
2994
  // ========================
2707
2995
 
2708
- hideControls: function() {
2709
- this.isHiddenControls = true;
2996
+ hideControls: function(andCaption) {
2997
+ var self = this,
2998
+ arr = ["infobar", "toolbar", "nav"];
2710
2999
 
2711
- this.$refs.container.removeClass("fancybox-show-infobar fancybox-show-toolbar fancybox-show-caption fancybox-show-nav");
3000
+ if (andCaption || !self.current.opts.preventCaptionOverlap) {
3001
+ arr.push("caption");
3002
+ }
3003
+
3004
+ this.$refs.container.removeClass(
3005
+ arr
3006
+ .map(function(i) {
3007
+ return "fancybox-show-" + i;
3008
+ })
3009
+ .join(" ")
3010
+ );
3011
+
3012
+ this.hasHiddenControls = true;
2712
3013
  },
2713
3014
 
2714
3015
  showControls: function() {
@@ -2716,27 +3017,22 @@
2716
3017
  opts = self.current ? self.current.opts : self.opts,
2717
3018
  $container = self.$refs.container;
2718
3019
 
2719
- self.isHiddenControls = false;
3020
+ self.hasHiddenControls = false;
2720
3021
  self.idleSecondsCounter = 0;
2721
3022
 
2722
3023
  $container
2723
3024
  .toggleClass("fancybox-show-toolbar", !!(opts.toolbar && opts.buttons))
2724
3025
  .toggleClass("fancybox-show-infobar", !!(opts.infobar && self.group.length > 1))
3026
+ .toggleClass("fancybox-show-caption", !!self.$caption)
2725
3027
  .toggleClass("fancybox-show-nav", !!(opts.arrows && self.group.length > 1))
2726
3028
  .toggleClass("fancybox-is-modal", !!opts.modal);
2727
-
2728
- if (self.$caption) {
2729
- $container.addClass("fancybox-show-caption ");
2730
- } else {
2731
- $container.removeClass("fancybox-show-caption");
2732
- }
2733
3029
  },
2734
3030
 
2735
3031
  // Toggle toolbar and caption
2736
3032
  // ==========================
2737
3033
 
2738
3034
  toggleControls: function() {
2739
- if (this.isHiddenControls) {
3035
+ if (this.hasHiddenControls) {
2740
3036
  this.showControls();
2741
3037
  } else {
2742
3038
  this.hideControls();
@@ -2745,7 +3041,7 @@
2745
3041
  });
2746
3042
 
2747
3043
  $.fancybox = {
2748
- version: "3.3.5",
3044
+ version: "3.5.2",
2749
3045
  defaults: defaults,
2750
3046
 
2751
3047
  // Get current instance and execute a command.
@@ -2794,9 +3090,8 @@
2794
3090
  instance.close();
2795
3091
 
2796
3092
  // Try to find and close next instance
2797
-
2798
3093
  if (all === true) {
2799
- this.close();
3094
+ this.close(all);
2800
3095
  }
2801
3096
  }
2802
3097
  },
@@ -2813,8 +3108,7 @@
2813
3108
  // Try to detect mobile devices
2814
3109
  // ============================
2815
3110
 
2816
- isMobile:
2817
- document.createTouch !== undefined && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
3111
+ isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
2818
3112
 
2819
3113
  // Detect if 'translate3d' support is available
2820
3114
  // ============================================
@@ -2879,7 +3173,9 @@
2879
3173
  }
2880
3174
 
2881
3175
  if (props.scaleX !== undefined && props.scaleY !== undefined) {
2882
- str = (str.length ? str + " " : "") + "scale(" + props.scaleX + ", " + props.scaleY + ")";
3176
+ str += " scale(" + props.scaleX + ", " + props.scaleY + ")";
3177
+ } else if (props.scaleX !== undefined) {
3178
+ str += " scaleX(" + props.scaleX + ")";
2883
3179
  }
2884
3180
 
2885
3181
  if (str.length) {
@@ -2905,18 +3201,17 @@
2905
3201
  // =============================
2906
3202
 
2907
3203
  animate: function($el, to, duration, callback, leaveAnimationName) {
2908
- var final = false;
3204
+ var self = this,
3205
+ from;
2909
3206
 
2910
3207
  if ($.isFunction(duration)) {
2911
3208
  callback = duration;
2912
3209
  duration = null;
2913
3210
  }
2914
3211
 
2915
- if (!$.isPlainObject(to)) {
2916
- $el.removeAttr("style");
2917
- }
3212
+ self.stop($el);
2918
3213
 
2919
- $.fancybox.stop($el);
3214
+ from = self.getTranslate($el);
2920
3215
 
2921
3216
  $el.on(transitionEnd, function(e) {
2922
3217
  // Skip events from child elements and z-index change
@@ -2924,15 +3219,22 @@
2924
3219
  return;
2925
3220
  }
2926
3221
 
2927
- $.fancybox.stop($el);
3222
+ self.stop($el);
2928
3223
 
2929
- if (final) {
2930
- $.fancybox.setTranslate($el, final);
3224
+ if ($.isNumeric(duration)) {
3225
+ $el.css("transition-duration", "");
2931
3226
  }
2932
3227
 
2933
3228
  if ($.isPlainObject(to)) {
2934
- if (leaveAnimationName === false) {
2935
- $el.removeAttr("style");
3229
+ if (to.scaleX !== undefined && to.scaleY !== undefined) {
3230
+ self.setTranslate($el, {
3231
+ top: to.top,
3232
+ left: to.left,
3233
+ width: from.width * to.scaleX,
3234
+ height: from.height * to.scaleY,
3235
+ scaleX: 1,
3236
+ scaleY: 1
3237
+ });
2936
3238
  }
2937
3239
  } else if (leaveAnimationName !== true) {
2938
3240
  $el.removeClass(to);
@@ -2950,13 +3252,6 @@
2950
3252
  // Start animation by changing CSS properties or class name
2951
3253
  if ($.isPlainObject(to)) {
2952
3254
  if (to.scaleX !== undefined && to.scaleY !== undefined) {
2953
- final = $.extend({}, to, {
2954
- width: $el.width() * to.scaleX,
2955
- height: $el.height() * to.scaleY,
2956
- scaleX: 1,
2957
- scaleY: 1
2958
- });
2959
-
2960
3255
  delete to.width;
2961
3256
  delete to.height;
2962
3257
 
@@ -2974,16 +3269,20 @@
2974
3269
  $el.data(
2975
3270
  "timer",
2976
3271
  setTimeout(function() {
2977
- $el.trigger("transitionend");
2978
- }, duration + 16)
3272
+ $el.trigger(transitionEnd);
3273
+ }, duration + 33)
2979
3274
  );
2980
3275
  },
2981
3276
 
2982
- stop: function($el) {
3277
+ stop: function($el, callCallback) {
2983
3278
  if ($el && $el.length) {
2984
3279
  clearTimeout($el.data("timer"));
2985
3280
 
2986
- $el.off("transitionend").css("transition-duration", "");
3281
+ if (callCallback) {
3282
+ $el.trigger(transitionEnd);
3283
+ }
3284
+
3285
+ $el.off(transitionEnd).css("transition-duration", "");
2987
3286
 
2988
3287
  $el.parent().removeClass("fancybox-is-scaling");
2989
3288
  }
@@ -2997,7 +3296,8 @@
2997
3296
  var items = [],
2998
3297
  index = 0,
2999
3298
  $target,
3000
- value;
3299
+ value,
3300
+ instance;
3001
3301
 
3002
3302
  // Avoid opening multiple times
3003
3303
  if (e && e.isDefaultPrevented()) {
@@ -3006,27 +3306,44 @@
3006
3306
 
3007
3307
  e.preventDefault();
3008
3308
 
3009
- opts = e && e.data ? e.data.options : opts || {};
3309
+ opts = opts || {};
3310
+
3311
+ if (e && e.data) {
3312
+ opts = mergeOpts(e.data.options, opts);
3313
+ }
3010
3314
 
3011
- $target = opts.$target || $(e.currentTarget);
3012
- value = $target.attr("data-fancybox") || "";
3315
+ $target = opts.$target || $(e.currentTarget).trigger("blur");
3316
+ instance = $.fancybox.getInstance();
3013
3317
 
3014
- // Get all related items and find index for clicked one
3015
- if (value) {
3016
- items = opts.selector ? $(opts.selector) : e.data ? e.data.items : [];
3017
- items = items.length ? items.filter('[data-fancybox="' + value + '"]') : $('[data-fancybox="' + value + '"]');
3318
+ if (instance && instance.$trigger && instance.$trigger.is($target)) {
3319
+ return;
3320
+ }
3018
3321
 
3019
- index = items.index($target);
3322
+ if (opts.selector) {
3323
+ items = $(opts.selector);
3324
+ } else {
3325
+ // Get all related items and find index for clicked one
3326
+ value = $target.attr("data-fancybox") || "";
3020
3327
 
3021
- // Sometimes current item can not be found (for example, if some script clones items)
3022
- if (index < 0) {
3023
- index = 0;
3328
+ if (value) {
3329
+ items = e.data ? e.data.items : [];
3330
+ items = items.length ? items.filter('[data-fancybox="' + value + '"]') : $('[data-fancybox="' + value + '"]');
3331
+ } else {
3332
+ items = [$target];
3024
3333
  }
3025
- } else {
3026
- items = [$target];
3027
3334
  }
3028
3335
 
3029
- $.fancybox.open(items, opts, index);
3336
+ index = $(items).index($target);
3337
+
3338
+ // Sometimes current item can not be found
3339
+ if (index < 0) {
3340
+ index = 0;
3341
+ }
3342
+
3343
+ instance = $.fancybox.open(items, opts, index);
3344
+
3345
+ // Save last active element
3346
+ instance.$trigger = $target;
3030
3347
  }
3031
3348
 
3032
3349
  // Create a jQuery plugin
@@ -3065,13 +3382,43 @@
3065
3382
  // Enable "trigger elements"
3066
3383
  // =========================
3067
3384
 
3068
- $D.on("click.fb-start", "[data-trigger]", function(e) {
3069
- _run(e, {
3070
- $target: $('[data-fancybox="' + $(e.currentTarget).attr("data-trigger") + '"]').eq($(e.currentTarget).attr("data-index") || 0),
3071
- $trigger: $(this)
3385
+ $D.on("click.fb-start", "[data-fancybox-trigger]", function(e) {
3386
+ $('[data-fancybox="' + $(this).attr("data-fancybox-trigger") + '"]')
3387
+ .eq($(this).attr("data-fancybox-index") || 0)
3388
+ .trigger("click.fb-start", {
3389
+ $trigger: $(this)
3390
+ });
3391
+ });
3392
+
3393
+ // Track focus event for better accessibility styling
3394
+ // ==================================================
3395
+ (function() {
3396
+ var buttonStr = ".fancybox-button",
3397
+ focusStr = "fancybox-focus",
3398
+ $pressed = null;
3399
+
3400
+ $D.on("mousedown mouseup focus blur", buttonStr, function(e) {
3401
+ switch (e.type) {
3402
+ case "mousedown":
3403
+ $pressed = $(this);
3404
+ break;
3405
+ case "mouseup":
3406
+ $pressed = null;
3407
+ break;
3408
+ case "focusin":
3409
+ $(buttonStr).removeClass(focusStr);
3410
+
3411
+ if (!$(this).is($pressed) && !$(this).is("[disabled]")) {
3412
+ $(this).addClass(focusStr);
3413
+ }
3414
+ break;
3415
+ case "focusout":
3416
+ $(buttonStr).removeClass(focusStr);
3417
+ break;
3418
+ }
3072
3419
  });
3073
- });
3074
- })(window, document, window.jQuery || jQuery);
3420
+ })();
3421
+ })(window, document, jQuery);
3075
3422
 
3076
3423
  // ==========================================================================
3077
3424
  //
@@ -3082,32 +3429,7 @@
3082
3429
  (function($) {
3083
3430
  "use strict";
3084
3431
 
3085
- // Formats matching url to final form
3086
-
3087
- var format = function(url, rez, params) {
3088
- if (!url) {
3089
- return;
3090
- }
3091
-
3092
- params = params || "";
3093
-
3094
- if ($.type(params) === "object") {
3095
- params = $.param(params, true);
3096
- }
3097
-
3098
- $.each(rez, function(key, value) {
3099
- url = url.replace("$" + key, value || "");
3100
- });
3101
-
3102
- if (params.length) {
3103
- url += (url.indexOf("?") > 0 ? "&" : "?") + params;
3104
- }
3105
-
3106
- return url;
3107
- };
3108
-
3109
3432
  // Object containing properties for each media type
3110
-
3111
3433
  var defaults = {
3112
3434
  youtube: {
3113
3435
  matcher: /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
@@ -3123,7 +3445,7 @@
3123
3445
  },
3124
3446
  paramPlace: 8,
3125
3447
  type: "iframe",
3126
- url: "//www.youtube.com/embed/$4",
3448
+ url: "//www.youtube-nocookie.com/embed/$4",
3127
3449
  thumb: "//img.youtube.com/vi/$4/hqdefault.jpg"
3128
3450
  },
3129
3451
 
@@ -3135,8 +3457,7 @@
3135
3457
  show_title: 1,
3136
3458
  show_byline: 1,
3137
3459
  show_portrait: 0,
3138
- fullscreen: 1,
3139
- api: 1
3460
+ fullscreen: 1
3140
3461
  },
3141
3462
  paramPlace: 3,
3142
3463
  type: "iframe",
@@ -3182,6 +3503,29 @@
3182
3503
  }
3183
3504
  };
3184
3505
 
3506
+ // Formats matching url to final form
3507
+ var format = function(url, rez, params) {
3508
+ if (!url) {
3509
+ return;
3510
+ }
3511
+
3512
+ params = params || "";
3513
+
3514
+ if ($.type(params) === "object") {
3515
+ params = $.param(params, true);
3516
+ }
3517
+
3518
+ $.each(rez, function(key, value) {
3519
+ url = url.replace("$" + key, value || "");
3520
+ });
3521
+
3522
+ if (params.length) {
3523
+ url += (url.indexOf("?") > 0 ? "&" : "?") + params;
3524
+ }
3525
+
3526
+ return url;
3527
+ };
3528
+
3185
3529
  $(document).on("objectNeedsType.fb", function(e, instance, item) {
3186
3530
  var url = item.src || "",
3187
3531
  type = false,
@@ -3273,7 +3617,99 @@
3273
3617
  item.type = item.opts.defaultType;
3274
3618
  }
3275
3619
  });
3276
- })(window.jQuery || jQuery);
3620
+
3621
+ // Load YouTube/Video API on request to detect when video finished playing
3622
+ var VideoAPILoader = {
3623
+ youtube: {
3624
+ src: "https://www.youtube.com/iframe_api",
3625
+ class: "YT",
3626
+ loading: false,
3627
+ loaded: false
3628
+ },
3629
+
3630
+ vimeo: {
3631
+ src: "https://player.vimeo.com/api/player.js",
3632
+ class: "Vimeo",
3633
+ loading: false,
3634
+ loaded: false
3635
+ },
3636
+
3637
+ load: function(vendor) {
3638
+ var _this = this,
3639
+ script;
3640
+
3641
+ if (this[vendor].loaded) {
3642
+ setTimeout(function() {
3643
+ _this.done(vendor);
3644
+ });
3645
+ return;
3646
+ }
3647
+
3648
+ if (this[vendor].loading) {
3649
+ return;
3650
+ }
3651
+
3652
+ this[vendor].loading = true;
3653
+
3654
+ script = document.createElement("script");
3655
+ script.type = "text/javascript";
3656
+ script.src = this[vendor].src;
3657
+
3658
+ if (vendor === "youtube") {
3659
+ window.onYouTubeIframeAPIReady = function() {
3660
+ _this[vendor].loaded = true;
3661
+ _this.done(vendor);
3662
+ };
3663
+ } else {
3664
+ script.onload = function() {
3665
+ _this[vendor].loaded = true;
3666
+ _this.done(vendor);
3667
+ };
3668
+ }
3669
+
3670
+ document.body.appendChild(script);
3671
+ },
3672
+ done: function(vendor) {
3673
+ var instance, $el, player;
3674
+
3675
+ if (vendor === "youtube") {
3676
+ delete window.onYouTubeIframeAPIReady;
3677
+ }
3678
+
3679
+ instance = $.fancybox.getInstance();
3680
+
3681
+ if (instance) {
3682
+ $el = instance.current.$content.find("iframe");
3683
+
3684
+ if (vendor === "youtube" && YT !== undefined && YT) {
3685
+ player = new YT.Player($el.attr("id"), {
3686
+ events: {
3687
+ onStateChange: function(e) {
3688
+ if (e.data == 0) {
3689
+ instance.next();
3690
+ }
3691
+ }
3692
+ }
3693
+ });
3694
+ } else if (vendor === "vimeo" && Vimeo !== undefined && Vimeo) {
3695
+ player = new Vimeo.Player($el);
3696
+
3697
+ player.on("ended", function() {
3698
+ instance.next();
3699
+ });
3700
+ }
3701
+ }
3702
+ }
3703
+ };
3704
+
3705
+ $(document).on({
3706
+ "afterShow.fb": function(e, instance, current) {
3707
+ if (instance.group.length > 1 && (current.contentSource === "youtube" || current.contentSource === "vimeo")) {
3708
+ VideoAPILoader.load(current.contentSource);
3709
+ }
3710
+ }
3711
+ });
3712
+ })(jQuery);
3277
3713
 
3278
3714
  // ==========================================================================
3279
3715
  //
@@ -3348,7 +3784,7 @@
3348
3784
 
3349
3785
  var isClickable = function($el) {
3350
3786
  if (
3351
- $el.is('a,area,button,[role="button"],input,label,select,summary,textarea,video,audio') ||
3787
+ $el.is('a,area,button,[role="button"],input,label,select,summary,textarea,video,audio,iframe') ||
3352
3788
  $.isFunction($el.get(0).onclick) ||
3353
3789
  $el.data("selectable")
3354
3790
  ) {
@@ -3409,7 +3845,21 @@
3409
3845
  };
3410
3846
 
3411
3847
  Guestures.prototype.destroy = function() {
3412
- this.$container.off(".fb.touch");
3848
+ var self = this;
3849
+
3850
+ self.$container.off(".fb.touch");
3851
+
3852
+ $(document).off(".fb.touch");
3853
+
3854
+ if (self.requestId) {
3855
+ cancelAFrame(self.requestId);
3856
+ self.requestId = null;
3857
+ }
3858
+
3859
+ if (self.tapped) {
3860
+ clearTimeout(self.tapped);
3861
+ self.tapped = null;
3862
+ }
3413
3863
  };
3414
3864
 
3415
3865
  Guestures.prototype.ontouchstart = function(e) {
@@ -3417,6 +3867,7 @@
3417
3867
  $target = $(e.target),
3418
3868
  instance = self.instance,
3419
3869
  current = instance.current,
3870
+ $slide = current.$slide,
3420
3871
  $content = current.$content,
3421
3872
  isTouchDevice = e.type == "touchstart";
3422
3873
 
@@ -3431,17 +3882,16 @@
3431
3882
  }
3432
3883
 
3433
3884
  // Ignore taping on links, buttons, input elements
3434
- if (!$target.length || isClickable($target) || isClickable($target.parent())) {
3885
+ if (!$slide.length || !$target.length || isClickable($target) || isClickable($target.parent())) {
3435
3886
  return;
3436
3887
  }
3437
-
3438
3888
  // Ignore clicks on the scrollbar
3439
3889
  if (!$target.is("img") && e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left) {
3440
3890
  return;
3441
3891
  }
3442
3892
 
3443
3893
  // Ignore clicks while zooming or closing
3444
- if (!current || instance.isAnimating || instance.isClosing) {
3894
+ if (!current || instance.isAnimating || current.$slide.hasClass("fancybox-animated")) {
3445
3895
  e.stopPropagation();
3446
3896
  e.preventDefault();
3447
3897
 
@@ -3454,7 +3904,10 @@
3454
3904
  return;
3455
3905
  }
3456
3906
 
3457
- e.stopPropagation();
3907
+ // Allow other scripts to catch touch event if "touch" is set to false
3908
+ if (current.touch) {
3909
+ e.stopPropagation();
3910
+ }
3458
3911
 
3459
3912
  self.startEvent = e;
3460
3913
 
@@ -3467,16 +3920,17 @@
3467
3920
  self.isSwiping = false;
3468
3921
  self.isZooming = false;
3469
3922
  self.isScrolling = false;
3923
+ self.canPan = instance.canPan();
3470
3924
 
3471
3925
  self.startTime = new Date().getTime();
3472
3926
  self.distanceX = self.distanceY = self.distance = 0;
3473
3927
 
3474
- self.canvasWidth = Math.round(current.$slide[0].clientWidth);
3475
- self.canvasHeight = Math.round(current.$slide[0].clientHeight);
3928
+ self.canvasWidth = Math.round($slide[0].clientWidth);
3929
+ self.canvasHeight = Math.round($slide[0].clientHeight);
3476
3930
 
3477
3931
  self.contentLastPos = null;
3478
3932
  self.contentStartPos = $.fancybox.getTranslate(self.$content) || {top: 0, left: 0};
3479
- self.sliderStartPos = self.sliderLastPos || $.fancybox.getTranslate(current.$slide);
3933
+ self.sliderStartPos = $.fancybox.getTranslate($slide);
3480
3934
 
3481
3935
  // Since position will be absolute, but we need to make it relative to the stage
3482
3936
  self.stagePos = $.fancybox.getTranslate(instance.$refs.stage);
@@ -3496,32 +3950,38 @@
3496
3950
  document.addEventListener("scroll", self.onscroll, true);
3497
3951
  }
3498
3952
 
3499
- if (!(self.opts || instance.canPan()) || !($target.is(self.$stage) || self.$stage.find($target).length)) {
3953
+ // Skip if clicked outside the sliding area
3954
+ if (!(self.opts || self.canPan) || !($target.is(self.$stage) || self.$stage.find($target).length)) {
3500
3955
  if ($target.is(".fancybox-image")) {
3501
3956
  e.preventDefault();
3502
3957
  }
3503
3958
 
3504
- return;
3959
+ if (!($.fancybox.isMobile && $target.hasClass("fancybox-caption"))) {
3960
+ return;
3961
+ }
3505
3962
  }
3506
3963
 
3507
- if (!($.fancybox.isMobile && (isScrollable($target) || isScrollable($target.parent())))) {
3964
+ self.isScrollable = isScrollable($target) || isScrollable($target.parent());
3965
+
3966
+ // Check if element is scrollable and try to prevent default behavior (scrolling)
3967
+ if (!($.fancybox.isMobile && self.isScrollable)) {
3508
3968
  e.preventDefault();
3509
3969
  }
3510
3970
 
3971
+ // One finger or mouse click - swipe or pan an image
3511
3972
  if (self.startPoints.length === 1 || current.hasError) {
3512
- if (self.instance.canPan()) {
3973
+ if (self.canPan) {
3513
3974
  $.fancybox.stop(self.$content);
3514
3975
 
3515
- self.$content.css("transition-duration", "");
3516
-
3517
3976
  self.isPanning = true;
3518
3977
  } else {
3519
3978
  self.isSwiping = true;
3520
3979
  }
3521
3980
 
3522
- self.$container.addClass("fancybox-controls--isGrabbing");
3981
+ self.$container.addClass("fancybox-is-grabbing");
3523
3982
  }
3524
3983
 
3984
+ // Two fingers - zoom image
3525
3985
  if (self.startPoints.length === 2 && current.type === "image" && (current.isLoaded || current.$ghost)) {
3526
3986
  self.canTap = false;
3527
3987
  self.isSwiping = false;
@@ -3531,8 +3991,6 @@
3531
3991
 
3532
3992
  $.fancybox.stop(self.$content);
3533
3993
 
3534
- self.$content.css("transition-duration", "");
3535
-
3536
3994
  self.centerPointStartX = (self.startPoints[0].x + self.startPoints[1].x) * 0.5 - $(window).scrollLeft();
3537
3995
  self.centerPointStartY = (self.startPoints[0].y + self.startPoints[1].y) * 0.5 - $(window).scrollTop();
3538
3996
 
@@ -3552,8 +4010,7 @@
3552
4010
  };
3553
4011
 
3554
4012
  Guestures.prototype.ontouchmove = function(e) {
3555
- var self = this,
3556
- $target = $(e.target);
4013
+ var self = this;
3557
4014
 
3558
4015
  // Make sure user has not released over iframe or disabled element
3559
4016
  if (e.originalEvent.buttons !== undefined && e.originalEvent.buttons === 0) {
@@ -3561,15 +4018,14 @@
3561
4018
  return;
3562
4019
  }
3563
4020
 
3564
- if (self.isScrolling || !($target.is(self.$stage) || self.$stage.find($target).length)) {
4021
+ if (self.isScrolling) {
3565
4022
  self.canTap = false;
3566
-
3567
4023
  return;
3568
4024
  }
3569
4025
 
3570
4026
  self.newPoints = getPointerXY(e);
3571
4027
 
3572
- if (!(self.opts || self.instance.canPan()) || !self.newPoints.length || !self.newPoints.length) {
4028
+ if (!(self.opts || self.canPan) || !self.newPoints.length || !self.newPoints.length) {
3573
4029
  return;
3574
4030
  }
3575
4031
 
@@ -3596,6 +4052,7 @@
3596
4052
 
3597
4053
  Guestures.prototype.onSwipe = function(e) {
3598
4054
  var self = this,
4055
+ instance = self.instance,
3599
4056
  swiping = self.isSwiping,
3600
4057
  left = self.sliderStartPos.left || 0,
3601
4058
  angle;
@@ -3606,44 +4063,60 @@
3606
4063
  if (Math.abs(self.distance) > 10) {
3607
4064
  self.canTap = false;
3608
4065
 
3609
- if (self.instance.group.length < 2 && self.opts.vertical) {
4066
+ if (instance.group.length < 2 && self.opts.vertical) {
3610
4067
  self.isSwiping = "y";
3611
- } else if (self.instance.isDragging || self.opts.vertical === false || (self.opts.vertical === "auto" && $(window).width() > 800)) {
4068
+ } else if (instance.isDragging || self.opts.vertical === false || (self.opts.vertical === "auto" && $(window).width() > 800)) {
3612
4069
  self.isSwiping = "x";
3613
4070
  } else {
3614
- angle = Math.abs(Math.atan2(self.distanceY, self.distanceX) * 180 / Math.PI);
4071
+ angle = Math.abs((Math.atan2(self.distanceY, self.distanceX) * 180) / Math.PI);
3615
4072
 
3616
4073
  self.isSwiping = angle > 45 && angle < 135 ? "y" : "x";
3617
4074
  }
3618
4075
 
3619
- self.canTap = false;
3620
-
3621
- if (self.isSwiping === "y" && $.fancybox.isMobile && (isScrollable(self.$target) || isScrollable(self.$target.parent()))) {
4076
+ if (self.isSwiping === "y" && $.fancybox.isMobile && self.isScrollable) {
3622
4077
  self.isScrolling = true;
3623
4078
 
3624
4079
  return;
3625
4080
  }
3626
4081
 
3627
- self.instance.isDragging = self.isSwiping;
4082
+ instance.isDragging = self.isSwiping;
3628
4083
 
3629
4084
  // Reset points to avoid jumping, because we dropped first swipes to calculate the angle
3630
4085
  self.startPoints = self.newPoints;
3631
4086
 
3632
- $.each(self.instance.slides, function(index, slide) {
4087
+ $.each(instance.slides, function(index, slide) {
4088
+ var slidePos, stagePos;
4089
+
3633
4090
  $.fancybox.stop(slide.$slide);
3634
4091
 
3635
- slide.$slide.css("transition-duration", "");
4092
+ slidePos = $.fancybox.getTranslate(slide.$slide);
4093
+ stagePos = $.fancybox.getTranslate(instance.$refs.stage);
3636
4094
 
3637
- slide.inTransition = false;
4095
+ slide.$slide
4096
+ .css({
4097
+ transform: "",
4098
+ opacity: "",
4099
+ "transition-duration": ""
4100
+ })
4101
+ .removeClass("fancybox-animated")
4102
+ .removeClass(function(index, className) {
4103
+ return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" ");
4104
+ });
3638
4105
 
3639
- if (slide.pos === self.instance.current.pos) {
3640
- self.sliderStartPos.left = $.fancybox.getTranslate(slide.$slide).left - $.fancybox.getTranslate(self.instance.$refs.stage).left;
4106
+ if (slide.pos === instance.current.pos) {
4107
+ self.sliderStartPos.top = slidePos.top - stagePos.top;
4108
+ self.sliderStartPos.left = slidePos.left - stagePos.left;
3641
4109
  }
4110
+
4111
+ $.fancybox.setTranslate(slide.$slide, {
4112
+ top: slidePos.top - stagePos.top,
4113
+ left: slidePos.left - stagePos.left
4114
+ });
3642
4115
  });
3643
4116
 
3644
4117
  // Stop slideshow
3645
- if (self.instance.SlideShow && self.instance.SlideShow.isActive) {
3646
- self.instance.SlideShow.stop();
4118
+ if (instance.SlideShow && instance.SlideShow.isActive) {
4119
+ instance.SlideShow.stop();
3647
4120
  }
3648
4121
  }
3649
4122
 
@@ -3710,8 +4183,6 @@
3710
4183
 
3711
4184
  if (self.requestId) {
3712
4185
  cancelAFrame(self.requestId);
3713
-
3714
- self.requestId = null;
3715
4186
  }
3716
4187
 
3717
4188
  self.requestId = requestAFrame(function() {
@@ -3860,8 +4331,6 @@
3860
4331
 
3861
4332
  if (self.requestId) {
3862
4333
  cancelAFrame(self.requestId);
3863
-
3864
- self.requestId = null;
3865
4334
  }
3866
4335
 
3867
4336
  self.requestId = requestAFrame(function() {
@@ -3871,7 +4340,6 @@
3871
4340
 
3872
4341
  Guestures.prototype.ontouchend = function(e) {
3873
4342
  var self = this;
3874
- var dMs = Math.max(new Date().getTime() - self.startTime, 1);
3875
4343
 
3876
4344
  var swiping = self.isSwiping;
3877
4345
  var panning = self.isPanning;
@@ -3879,8 +4347,9 @@
3879
4347
  var scrolling = self.isScrolling;
3880
4348
 
3881
4349
  self.endPoints = getPointerXY(e);
4350
+ self.dMs = Math.max(new Date().getTime() - self.startTime, 1);
3882
4351
 
3883
- self.$container.removeClass("fancybox-controls--isGrabbing");
4352
+ self.$container.removeClass("fancybox-is-grabbing");
3884
4353
 
3885
4354
  $(document).off(".fb.touch");
3886
4355
 
@@ -3903,13 +4372,11 @@
3903
4372
  return self.onTap(e);
3904
4373
  }
3905
4374
 
3906
- self.speed = 366;
4375
+ self.speed = 100;
3907
4376
 
3908
4377
  // Speed in px/ms
3909
- self.velocityX = self.distanceX / dMs * 0.5;
3910
- self.velocityY = self.distanceY / dMs * 0.5;
3911
-
3912
- self.speedX = Math.max(self.speed * 0.5, Math.min(self.speed * 1.5, 1 / Math.abs(self.velocityX) * self.speed));
4378
+ self.velocityX = (self.distanceX / self.dMs) * 0.5;
4379
+ self.velocityY = (self.distanceY / self.dMs) * 0.5;
3913
4380
 
3914
4381
  if (panning) {
3915
4382
  self.endPanning();
@@ -3925,7 +4392,10 @@
3925
4392
  Guestures.prototype.endSwiping = function(swiping, scrolling) {
3926
4393
  var self = this,
3927
4394
  ret = false,
3928
- len = self.instance.group.length;
4395
+ len = self.instance.group.length,
4396
+ distanceX = Math.abs(self.distanceX),
4397
+ canAdvance = swiping == "x" && len > 1 && ((self.dMs > 130 && distanceX > 10) || distanceX > 50),
4398
+ speedX = 300;
3929
4399
 
3930
4400
  self.sliderLastPos = null;
3931
4401
 
@@ -3940,20 +4410,15 @@
3940
4410
  },
3941
4411
  200
3942
4412
  );
3943
-
3944
- ret = self.instance.close(true, 200);
3945
- } else if (swiping == "x" && self.distanceX > 50 && len > 1) {
3946
- ret = self.instance.previous(self.speedX);
3947
- } else if (swiping == "x" && self.distanceX < -50 && len > 1) {
3948
- ret = self.instance.next(self.speedX);
4413
+ ret = self.instance.close(true, 250);
4414
+ } else if (canAdvance && self.distanceX > 0) {
4415
+ ret = self.instance.previous(speedX);
4416
+ } else if (canAdvance && self.distanceX < 0) {
4417
+ ret = self.instance.next(speedX);
3949
4418
  }
3950
4419
 
3951
4420
  if (ret === false && (swiping == "x" || swiping == "y")) {
3952
- if (scrolling || len < 2) {
3953
- self.instance.centerSlide(self.instance.current, 150);
3954
- } else {
3955
- self.instance.jumpTo(self.instance.current.index);
3956
- }
4421
+ self.instance.centerSlide(200);
3957
4422
  }
3958
4423
 
3959
4424
  self.$container.removeClass("fancybox-is-sliding");
@@ -3962,20 +4427,22 @@
3962
4427
  // Limit panning from edges
3963
4428
  // ========================
3964
4429
  Guestures.prototype.endPanning = function() {
3965
- var self = this;
3966
- var newOffsetX, newOffsetY, newPos;
4430
+ var self = this,
4431
+ newOffsetX,
4432
+ newOffsetY,
4433
+ newPos;
3967
4434
 
3968
4435
  if (!self.contentLastPos) {
3969
4436
  return;
3970
4437
  }
3971
4438
 
3972
- if (self.opts.momentum === false) {
4439
+ if (self.opts.momentum === false || self.dMs > 350) {
3973
4440
  newOffsetX = self.contentLastPos.left;
3974
4441
  newOffsetY = self.contentLastPos.top;
3975
4442
  } else {
3976
4443
  // Continue movement
3977
- newOffsetX = self.contentLastPos.left + self.velocityX * self.speed;
3978
- newOffsetY = self.contentLastPos.top + self.velocityY * self.speed;
4444
+ newOffsetX = self.contentLastPos.left + self.velocityX * 500;
4445
+ newOffsetY = self.contentLastPos.top + self.velocityY * 500;
3979
4446
  }
3980
4447
 
3981
4448
  newPos = self.limitPosition(newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height);
@@ -4022,9 +4489,6 @@
4022
4489
  } else {
4023
4490
  newPos = self.limitPosition(newOffsetX, newOffsetY, newWidth, newHeight);
4024
4491
 
4025
- // Switch from scale() to width/height or animation will not work correctly
4026
- $.fancybox.setTranslate(self.$content, $.fancybox.getTranslate(self.$content));
4027
-
4028
4492
  $.fancybox.animate(self.$content, newPos, 150);
4029
4493
  }
4030
4494
  };
@@ -4061,7 +4525,7 @@
4061
4525
  break;
4062
4526
 
4063
4527
  case "toggleControls":
4064
- instance.toggleControls(true);
4528
+ instance.toggleControls();
4065
4529
 
4066
4530
  break;
4067
4531
 
@@ -4144,7 +4608,9 @@
4144
4608
  self.tapped = setTimeout(function() {
4145
4609
  self.tapped = null;
4146
4610
 
4147
- process("click" + where);
4611
+ if (!instance.isAnimating) {
4612
+ process("click" + where);
4613
+ }
4148
4614
  }, 500);
4149
4615
  } else {
4150
4616
  process("click" + where);
@@ -4154,12 +4620,18 @@
4154
4620
  return this;
4155
4621
  };
4156
4622
 
4157
- $(document).on("onActivate.fb", function(e, instance) {
4158
- if (instance && !instance.Guestures) {
4159
- instance.Guestures = new Guestures(instance);
4160
- }
4161
- });
4162
- })(window, document, window.jQuery || jQuery);
4623
+ $(document)
4624
+ .on("onActivate.fb", function(e, instance) {
4625
+ if (instance && !instance.Guestures) {
4626
+ instance.Guestures = new Guestures(instance);
4627
+ }
4628
+ })
4629
+ .on("beforeClose.fb", function(e, instance) {
4630
+ if (instance && instance.Guestures) {
4631
+ instance.Guestures.destroy();
4632
+ }
4633
+ });
4634
+ })(window, document, jQuery);
4163
4635
 
4164
4636
  // ==========================================================================
4165
4637
  //
@@ -4177,15 +4649,14 @@
4177
4649
  btnTpl: {
4178
4650
  slideShow:
4179
4651
  '<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}">' +
4180
- '<svg viewBox="0 0 40 40">' +
4181
- '<path d="M13,12 L27,20 L13,27 Z" />' +
4182
- '<path d="M15,10 v19 M23,10 v19" />' +
4183
- "</svg>" +
4652
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.5 5.4v13.2l11-6.6z"/></svg>' +
4653
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.33 5.75h2.2v12.5h-2.2V5.75zm5.15 0h2.2v12.5h-2.2V5.75z"/></svg>' +
4184
4654
  "</button>"
4185
4655
  },
4186
4656
  slideShow: {
4187
4657
  autoStart: false,
4188
- speed: 3000
4658
+ speed: 3000,
4659
+ progress: true
4189
4660
  }
4190
4661
  });
4191
4662
 
@@ -4200,35 +4671,45 @@
4200
4671
  $button: null,
4201
4672
 
4202
4673
  init: function() {
4203
- var self = this;
4674
+ var self = this,
4675
+ instance = self.instance,
4676
+ opts = instance.group[instance.currIndex].opts.slideShow;
4204
4677
 
4205
- self.$button = self.instance.$refs.toolbar.find("[data-fancybox-play]").on("click", function() {
4678
+ self.$button = instance.$refs.toolbar.find("[data-fancybox-play]").on("click", function() {
4206
4679
  self.toggle();
4207
4680
  });
4208
4681
 
4209
- if (self.instance.group.length < 2 || !self.instance.group[self.instance.currIndex].opts.slideShow) {
4682
+ if (instance.group.length < 2 || !opts) {
4210
4683
  self.$button.hide();
4684
+ } else if (opts.progress) {
4685
+ self.$progress = $('<div class="fancybox-progress"></div>').appendTo(instance.$refs.inner);
4211
4686
  }
4212
4687
  },
4213
4688
 
4214
4689
  set: function(force) {
4215
- var self = this;
4690
+ var self = this,
4691
+ instance = self.instance,
4692
+ current = instance.current;
4216
4693
 
4217
4694
  // Check if reached last element
4218
- if (
4219
- self.instance &&
4220
- self.instance.current &&
4221
- (force === true || self.instance.current.opts.loop || self.instance.currIndex < self.instance.group.length - 1)
4222
- ) {
4223
- self.timer = setTimeout(function() {
4224
- if (self.isActive) {
4225
- self.instance.jumpTo((self.instance.currIndex + 1) % self.instance.group.length);
4695
+ if (current && (force === true || current.opts.loop || instance.currIndex < instance.group.length - 1)) {
4696
+ if (self.isActive && current.contentType !== "video") {
4697
+ if (self.$progress) {
4698
+ $.fancybox.animate(self.$progress.show(), {scaleX: 1}, current.opts.slideShow.speed);
4226
4699
  }
4227
- }, self.instance.current.opts.slideShow.speed);
4700
+
4701
+ self.timer = setTimeout(function() {
4702
+ if (!instance.current.opts.loop && instance.current.index == instance.group.length - 1) {
4703
+ instance.jumpTo(0);
4704
+ } else {
4705
+ instance.next();
4706
+ }
4707
+ }, current.opts.slideShow.speed);
4708
+ }
4228
4709
  } else {
4229
4710
  self.stop();
4230
- self.instance.idleSecondsCounter = 0;
4231
- self.instance.showControls();
4711
+ instance.idleSecondsCounter = 0;
4712
+ instance.showControls();
4232
4713
  }
4233
4714
  },
4234
4715
 
@@ -4238,36 +4719,50 @@
4238
4719
  clearTimeout(self.timer);
4239
4720
 
4240
4721
  self.timer = null;
4722
+
4723
+ if (self.$progress) {
4724
+ self.$progress.removeAttr("style").hide();
4725
+ }
4241
4726
  },
4242
4727
 
4243
4728
  start: function() {
4244
- var self = this;
4245
- var current = self.instance.current;
4729
+ var self = this,
4730
+ current = self.instance.current;
4246
4731
 
4247
4732
  if (current) {
4248
- self.isActive = true;
4249
-
4250
4733
  self.$button
4251
- .attr("title", current.opts.i18n[current.opts.lang].PLAY_STOP)
4734
+ .attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_STOP)
4252
4735
  .removeClass("fancybox-button--play")
4253
4736
  .addClass("fancybox-button--pause");
4254
4737
 
4255
- self.set(true);
4738
+ self.isActive = true;
4739
+
4740
+ if (current.isComplete) {
4741
+ self.set(true);
4742
+ }
4743
+
4744
+ self.instance.trigger("onSlideShowChange", true);
4256
4745
  }
4257
4746
  },
4258
4747
 
4259
4748
  stop: function() {
4260
- var self = this;
4261
- var current = self.instance.current;
4749
+ var self = this,
4750
+ current = self.instance.current;
4262
4751
 
4263
4752
  self.clear();
4264
4753
 
4265
4754
  self.$button
4266
- .attr("title", current.opts.i18n[current.opts.lang].PLAY_START)
4755
+ .attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_START)
4267
4756
  .removeClass("fancybox-button--pause")
4268
4757
  .addClass("fancybox-button--play");
4269
4758
 
4270
4759
  self.isActive = false;
4760
+
4761
+ self.instance.trigger("onSlideShowChange", false);
4762
+
4763
+ if (self.$progress) {
4764
+ self.$progress.removeAttr("style").hide();
4765
+ }
4271
4766
  },
4272
4767
 
4273
4768
  toggle: function() {
@@ -4330,8 +4825,8 @@
4330
4825
 
4331
4826
  // Page Visibility API to pause slideshow when window is not active
4332
4827
  $(document).on("visibilitychange", function() {
4333
- var instance = $.fancybox.getInstance();
4334
- var SlideShow = instance && instance.SlideShow;
4828
+ var instance = $.fancybox.getInstance(),
4829
+ SlideShow = instance && instance.SlideShow;
4335
4830
 
4336
4831
  if (SlideShow && SlideShow.isActive) {
4337
4832
  if (document.hidden) {
@@ -4341,7 +4836,7 @@
4341
4836
  }
4342
4837
  }
4343
4838
  });
4344
- })(document, window.jQuery || jQuery);
4839
+ })(document, jQuery);
4345
4840
 
4346
4841
  // ==========================================================================
4347
4842
  //
@@ -4402,59 +4897,82 @@
4402
4897
  return false;
4403
4898
  })();
4404
4899
 
4405
- // If browser does not have Full Screen API, then simply unset default button template and stop
4406
- if (!fn) {
4407
- if ($ && $.fancybox) {
4408
- $.fancybox.defaults.btnTpl.fullScreen = false;
4409
- }
4410
-
4411
- return;
4412
- }
4900
+ if (fn) {
4901
+ var FullScreen = {
4902
+ request: function(elem) {
4903
+ elem = elem || document.documentElement;
4413
4904
 
4414
- var FullScreen = {
4415
- request: function(elem) {
4416
- elem = elem || document.documentElement;
4905
+ elem[fn.requestFullscreen](elem.ALLOW_KEYBOARD_INPUT);
4906
+ },
4907
+ exit: function() {
4908
+ document[fn.exitFullscreen]();
4909
+ },
4910
+ toggle: function(elem) {
4911
+ elem = elem || document.documentElement;
4417
4912
 
4418
- elem[fn.requestFullscreen](elem.ALLOW_KEYBOARD_INPUT);
4419
- },
4420
- exit: function() {
4421
- document[fn.exitFullscreen]();
4422
- },
4423
- toggle: function(elem) {
4424
- elem = elem || document.documentElement;
4913
+ if (this.isFullscreen()) {
4914
+ this.exit();
4915
+ } else {
4916
+ this.request(elem);
4917
+ }
4918
+ },
4919
+ isFullscreen: function() {
4920
+ return Boolean(document[fn.fullscreenElement]);
4921
+ },
4922
+ enabled: function() {
4923
+ return Boolean(document[fn.fullscreenEnabled]);
4924
+ }
4925
+ };
4425
4926
 
4426
- if (this.isFullscreen()) {
4427
- this.exit();
4428
- } else {
4429
- this.request(elem);
4927
+ $.extend(true, $.fancybox.defaults, {
4928
+ btnTpl: {
4929
+ fullScreen:
4930
+ '<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fsenter" title="{{FULL_SCREEN}}">' +
4931
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>' +
4932
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 16h3v3h2v-5H5zm3-8H5v2h5V5H8zm6 11h2v-3h3v-2h-5zm2-11V5h-2v5h5V8z"/></svg>' +
4933
+ "</button>"
4934
+ },
4935
+ fullScreen: {
4936
+ autoStart: false
4430
4937
  }
4431
- },
4432
- isFullscreen: function() {
4433
- return Boolean(document[fn.fullscreenElement]);
4434
- },
4435
- enabled: function() {
4436
- return Boolean(document[fn.fullscreenEnabled]);
4437
- }
4438
- };
4938
+ });
4439
4939
 
4440
- $.extend(true, $.fancybox.defaults, {
4441
- btnTpl: {
4442
- fullScreen:
4443
- '<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fullscreen" title="{{FULL_SCREEN}}">' +
4444
- '<svg viewBox="0 0 40 40">' +
4445
- '<path d="M9,12 v16 h22 v-16 h-22 v8" />' +
4446
- "</svg>" +
4447
- "</button>"
4448
- },
4449
- fullScreen: {
4450
- autoStart: false
4451
- }
4452
- });
4940
+ $(document).on(fn.fullscreenchange, function() {
4941
+ var isFullscreen = FullScreen.isFullscreen(),
4942
+ instance = $.fancybox.getInstance();
4943
+
4944
+ if (instance) {
4945
+ // If image is zooming, then force to stop and reposition properly
4946
+ if (instance.current && instance.current.type === "image" && instance.isAnimating) {
4947
+ instance.current.$content.css("transition", "none");
4948
+
4949
+ instance.isAnimating = false;
4950
+
4951
+ instance.update(true, true, 0);
4952
+ }
4953
+
4954
+ instance.trigger("onFullscreenChange", isFullscreen);
4955
+
4956
+ instance.$refs.container.toggleClass("fancybox-is-fullscreen", isFullscreen);
4957
+
4958
+ instance.$refs.toolbar
4959
+ .find("[data-fancybox-fullscreen]")
4960
+ .toggleClass("fancybox-button--fsenter", !isFullscreen)
4961
+ .toggleClass("fancybox-button--fsexit", isFullscreen);
4962
+ }
4963
+ });
4964
+ }
4453
4965
 
4454
4966
  $(document).on({
4455
4967
  "onInit.fb": function(e, instance) {
4456
4968
  var $container;
4457
4969
 
4970
+ if (!fn) {
4971
+ instance.$refs.toolbar.find("[data-fancybox-fullscreen]").remove();
4972
+
4973
+ return;
4974
+ }
4975
+
4458
4976
  if (instance && instance.group[instance.currIndex].opts.fullScreen) {
4459
4977
  $container = instance.$refs.container;
4460
4978
 
@@ -4491,27 +5009,7 @@
4491
5009
  }
4492
5010
  }
4493
5011
  });
4494
-
4495
- $(document).on(fn.fullscreenchange, function() {
4496
- var isFullscreen = FullScreen.isFullscreen(),
4497
- instance = $.fancybox.getInstance();
4498
-
4499
- if (instance) {
4500
- // If image is zooming, then force to stop and reposition properly
4501
- if (instance.current && instance.current.type === "image" && instance.isAnimating) {
4502
- instance.current.$content.css("transition", "none");
4503
-
4504
- instance.isAnimating = false;
4505
-
4506
- instance.update(true, true, 0);
4507
- }
4508
-
4509
- instance.trigger("onFullscreenChange", isFullscreen);
4510
-
4511
- instance.$refs.container.toggleClass("fancybox-is-fullscreen", isFullscreen);
4512
- }
4513
- });
4514
- })(document, window.jQuery || jQuery);
5012
+ })(document, jQuery);
4515
5013
 
4516
5014
  // ==========================================================================
4517
5015
  //
@@ -4523,8 +5021,7 @@
4523
5021
  "use strict";
4524
5022
 
4525
5023
  var CLASS = "fancybox-thumbs",
4526
- CLASS_ACTIVE = CLASS + "-active",
4527
- CLASS_LOAD = CLASS + "-loading";
5024
+ CLASS_ACTIVE = CLASS + "-active";
4528
5025
 
4529
5026
  // Make sure there are default values
4530
5027
  $.fancybox.defaults = $.extend(
@@ -4533,9 +5030,7 @@
4533
5030
  btnTpl: {
4534
5031
  thumbs:
4535
5032
  '<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}">' +
4536
- '<svg viewBox="0 0 120 120">' +
4537
- '<path d="M30,30 h14 v14 h-14 Z M50,30 h14 v14 h-14 Z M70,30 h14 v14 h-14 Z M30,50 h14 v14 h-14 Z M50,50 h14 v14 h-14 Z M70,50 h14 v14 h-14 Z M30,70 h14 v14 h-14 Z M50,70 h14 v14 h-14 Z M70,70 h14 v14 h-14 Z" />' +
4538
- "</svg>" +
5033
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.59 14.59h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76H5.65v-3.76zm8.94-4.47h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76H5.65v-3.76zm8.94-4.47h3.76v3.76h-3.76V5.65zm-4.47 0h3.76v3.76h-3.76V5.65zm-4.47 0h3.76v3.76H5.65V5.65z"/></svg>' +
4539
5034
  "</button>"
4540
5035
  },
4541
5036
  thumbs: {
@@ -4561,28 +5056,29 @@
4561
5056
 
4562
5057
  init: function(instance) {
4563
5058
  var self = this,
4564
- first,
4565
- second;
5059
+ group = instance.group,
5060
+ enabled = 0;
4566
5061
 
4567
5062
  self.instance = instance;
5063
+ self.opts = group[instance.currIndex].opts.thumbs;
4568
5064
 
4569
5065
  instance.Thumbs = self;
4570
5066
 
4571
- self.opts = instance.group[instance.currIndex].opts.thumbs;
5067
+ self.$button = instance.$refs.toolbar.find("[data-fancybox-thumbs]");
4572
5068
 
4573
5069
  // Enable thumbs if at least two group items have thumbnails
4574
- first = instance.group[0];
4575
- first = first.opts.thumb || (first.opts.$thumb && first.opts.$thumb.length ? first.opts.$thumb.attr("src") : false);
5070
+ for (var i = 0, len = group.length; i < len; i++) {
5071
+ if (group[i].thumb) {
5072
+ enabled++;
5073
+ }
4576
5074
 
4577
- if (instance.group.length > 1) {
4578
- second = instance.group[1];
4579
- second = second.opts.thumb || (second.opts.$thumb && second.opts.$thumb.length ? second.opts.$thumb.attr("src") : false);
5075
+ if (enabled > 1) {
5076
+ break;
5077
+ }
4580
5078
  }
4581
5079
 
4582
- self.$button = instance.$refs.toolbar.find("[data-fancybox-thumbs]");
4583
-
4584
- if (self.opts && first && second && first && second) {
4585
- self.$button.show().on("click", function() {
5080
+ if (enabled > 1 && !!self.opts) {
5081
+ self.$button.removeAttr("style").on("click", function() {
4586
5082
  self.toggle();
4587
5083
  });
4588
5084
 
@@ -4609,31 +5105,29 @@
4609
5105
  );
4610
5106
 
4611
5107
  // Add "click" event that performs gallery navigation
4612
- self.$grid.on("click", "li", function() {
5108
+ self.$grid.on("click", "a", function() {
4613
5109
  instance.jumpTo($(this).attr("data-index"));
4614
5110
  });
4615
5111
  }
4616
5112
 
4617
5113
  // Build the list
4618
5114
  if (!self.$list) {
4619
- self.$list = $("<ul>").appendTo(self.$grid);
5115
+ self.$list = $('<div class="' + CLASS + '__list">').appendTo(self.$grid);
4620
5116
  }
4621
5117
 
4622
5118
  $.each(instance.group, function(i, item) {
4623
- src = item.opts.thumb || (item.opts.$thumb ? item.opts.$thumb.attr("src") : null);
5119
+ src = item.thumb;
4624
5120
 
4625
5121
  if (!src && item.type === "image") {
4626
5122
  src = item.src;
4627
5123
  }
4628
5124
 
4629
5125
  list.push(
4630
- '<li data-index="' +
5126
+ '<a href="javascript:;" tabindex="0" data-index="' +
4631
5127
  i +
4632
- '" tabindex="0" class="' +
4633
- CLASS_LOAD +
4634
5128
  '"' +
4635
- (src && src.length ? ' style="background-image:url(' + src + ')" />' : "") +
4636
- "></li>"
5129
+ (src && src.length ? ' style="background-image:url(' + src + ')"' : 'class="fancybox-thumbs-missing"') +
5130
+ "></a>"
4637
5131
  );
4638
5132
  });
4639
5133
 
@@ -4771,7 +5265,7 @@
4771
5265
  }
4772
5266
  }
4773
5267
  });
4774
- })(document, window.jQuery || jQuery);
5268
+ })(document, jQuery);
4775
5269
 
4776
5270
  //// ==========================================================================
4777
5271
  //
@@ -4786,9 +5280,7 @@
4786
5280
  btnTpl: {
4787
5281
  share:
4788
5282
  '<button data-fancybox-share class="fancybox-button fancybox-button--share" title="{{SHARE}}">' +
4789
- '<svg viewBox="0 0 40 40">' +
4790
- '<path d="M6,30 C8,18 19,16 23,16 L23,16 L23,10 L33,20 L23,29 L23,24 C19,24 8,27 6,30 Z">' +
4791
- "</svg>" +
5283
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M2.55 19c1.4-8.4 9.1-9.8 11.9-9.8V5l7 7-7 6.3v-3.5c-2.8 0-10.5 2.1-11.9 4.2z"/></svg>' +
4792
5284
  "</button>"
4793
5285
  },
4794
5286
  share: {
@@ -4814,7 +5306,7 @@
4814
5306
  "<span>Pinterest</span>" +
4815
5307
  "</a>" +
4816
5308
  "</p>" +
4817
- '<p><input class="fancybox-share__input" type="text" value="{{url_raw}}" /></p>' +
5309
+ '<p><input class="fancybox-share__input" type="text" value="{{url_raw}}" onclick="select()" /></p>' +
4818
5310
  "</div>"
4819
5311
  }
4820
5312
  });
@@ -4860,6 +5352,7 @@
4860
5352
  src: instance.translate(instance, tpl),
4861
5353
  type: "html",
4862
5354
  opts: {
5355
+ touch: false,
4863
5356
  animationEffect: false,
4864
5357
  afterLoad: function(shareInstance, shareCurrent) {
4865
5358
  // Close self if parent instance is closing
@@ -4868,15 +5361,18 @@
4868
5361
  });
4869
5362
 
4870
5363
  // Opening links in a popup window
4871
- shareCurrent.$content.find(".fancybox-share__links a").click(function() {
5364
+ shareCurrent.$content.find(".fancybox-share__button").click(function() {
4872
5365
  window.open(this.href, "Share", "width=550, height=450");
4873
5366
  return false;
4874
5367
  });
5368
+ },
5369
+ mobile: {
5370
+ autoFocus: false
4875
5371
  }
4876
5372
  }
4877
5373
  });
4878
5374
  });
4879
- })(document, window.jQuery || jQuery);
5375
+ })(document, jQuery);
4880
5376
 
4881
5377
  // ==========================================================================
4882
5378
  //
@@ -4884,7 +5380,7 @@
4884
5380
  // Enables linking to each modal
4885
5381
  //
4886
5382
  // ==========================================================================
4887
- (function(document, window, $) {
5383
+ (function(window, document, $) {
4888
5384
  "use strict";
4889
5385
 
4890
5386
  // Simple $.escapeSelector polyfill (for jQuery prior v3)
@@ -4927,13 +5423,12 @@
4927
5423
 
4928
5424
  // Trigger click evnt on links to open new fancyBox instance
4929
5425
  function triggerFromUrl(url) {
4930
- var $el;
4931
-
4932
5426
  if (url.gallery !== "") {
4933
- // If we can find element matching 'data-fancybox' atribute, then trigger click event for that.
4934
- // It should start fancyBox
4935
- $el = $("[data-fancybox='" + $.escapeSelector(url.gallery) + "']")
5427
+ // If we can find element matching 'data-fancybox' atribute,
5428
+ // then triggering click event should start fancyBox
5429
+ $("[data-fancybox='" + $.escapeSelector(url.gallery) + "']")
4936
5430
  .eq(url.index - 1)
5431
+ .focus()
4937
5432
  .trigger("click.fb-start");
4938
5433
  }
4939
5434
  }
@@ -4947,7 +5442,7 @@
4947
5442
  }
4948
5443
 
4949
5444
  opts = instance.current ? instance.current.opts : instance.opts;
4950
- ret = opts.hash || (opts.$orig ? opts.$orig.data("fancybox") : "");
5445
+ ret = opts.hash || (opts.$orig ? opts.$orig.data("fancybox") || opts.$orig.data("fancybox-trigger") : "");
4951
5446
 
4952
5447
  return ret === "" ? false : ret;
4953
5448
  }
@@ -5000,7 +5495,7 @@
5000
5495
  return;
5001
5496
  }
5002
5497
 
5003
- if (!instance.origHash) {
5498
+ if (firstRun && !instance.origHash) {
5004
5499
  instance.origHash = window.location.hash;
5005
5500
  }
5006
5501
 
@@ -5029,13 +5524,11 @@
5029
5524
  },
5030
5525
 
5031
5526
  "beforeClose.fb": function(e, instance, current) {
5032
- var gallery;
5033
-
5034
5527
  if (current.opts.hash === false) {
5035
5528
  return;
5036
5529
  }
5037
5530
 
5038
- gallery = getGalleryID(instance);
5531
+ clearTimeout(instance.hashTimer);
5039
5532
 
5040
5533
  // Goto previous history entry
5041
5534
  if (instance.currentHash && instance.hasCreatedHistory) {
@@ -5049,15 +5542,13 @@
5049
5542
  }
5050
5543
 
5051
5544
  instance.currentHash = null;
5052
-
5053
- clearTimeout(instance.hashTimer);
5054
5545
  }
5055
5546
  });
5056
5547
 
5057
5548
  // Check if need to start/close after url has changed
5058
5549
  $(window).on("hashchange.fb", function() {
5059
5550
  var url = parseUrl(),
5060
- fb;
5551
+ fb = null;
5061
5552
 
5062
5553
  // Find last fancyBox instance that has "hash"
5063
5554
  $.each(
@@ -5066,8 +5557,8 @@
5066
5557
  .reverse(),
5067
5558
  function(index, value) {
5068
5559
  var tmp = $(value).data("FancyBox");
5069
- //isClosing
5070
- if (tmp.currentHash) {
5560
+
5561
+ if (tmp && tmp.currentHash) {
5071
5562
  fb = tmp;
5072
5563
  return false;
5073
5564
  }
@@ -5076,7 +5567,7 @@
5076
5567
 
5077
5568
  if (fb) {
5078
5569
  // Now, compare hash values
5079
- if (fb.currentHash && fb.currentHash !== url.gallery + "-" + url.index && !(url.index === 1 && fb.currentHash == url.gallery)) {
5570
+ if (fb.currentHash !== url.gallery + "-" + url.index && !(url.index === 1 && fb.currentHash == url.gallery)) {
5080
5571
  fb.currentHash = null;
5081
5572
 
5082
5573
  fb.close();
@@ -5093,7 +5584,7 @@
5093
5584
  }
5094
5585
  }, 50);
5095
5586
  });
5096
- })(document, window, window.jQuery || jQuery);
5587
+ })(window, document, jQuery);
5097
5588
 
5098
5589
  // ==========================================================================
5099
5590
  //
@@ -5135,4 +5626,4 @@
5135
5626
  });
5136
5627
  }
5137
5628
  });
5138
- })(document, window.jQuery || jQuery);
5629
+ })(document, jQuery);