fancybox2-rails 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,164 @@
1
+ /*!
2
+ * Thumbnail helper for fancyBox
3
+ * version: 1.0.6
4
+ * @requires fancyBox v2.0 or later
5
+ *
6
+ * Usage:
7
+ * $(".fancybox").fancybox({
8
+ * helpers : {
9
+ * thumbs: {
10
+ * width : 50,
11
+ * height : 50
12
+ * }
13
+ * }
14
+ * });
15
+ *
16
+ * Options:
17
+ * width - thumbnail width
18
+ * height - thumbnail height
19
+ * source - function to obtain the URL of the thumbnail image
20
+ * position - 'top' or 'bottom'
21
+ *
22
+ */
23
+ (function ($) {
24
+ //Shortcut for fancyBox object
25
+ var F = $.fancybox;
26
+
27
+ //Add helper object
28
+ F.helpers.thumbs = {
29
+ wrap : null,
30
+ list : null,
31
+ width : 0,
32
+
33
+ //Default function to obtain the URL of the thumbnail image
34
+ source: function ( item ) {
35
+ var href;
36
+
37
+ if (item.element) {
38
+ href = $(item.element).find('img').attr('src');
39
+ }
40
+
41
+ if (!href && item.type === 'image' && item.href) {
42
+ href = item.href;
43
+ }
44
+
45
+ return href;
46
+ },
47
+
48
+ init: function (opts, obj) {
49
+ var that = this,
50
+ list,
51
+ thumbWidth = opts.width || 50,
52
+ thumbHeight = opts.height || 50,
53
+ thumbSource = opts.source || this.source;
54
+
55
+ //Build list structure
56
+ list = '';
57
+
58
+ for (var n = 0; n < obj.group.length; n++) {
59
+ list += '<li><a style="width:' + thumbWidth + 'px;height:' + thumbHeight + 'px;" href="javascript:jQuery.fancybox.jumpto(' + n + ');"></a></li>';
60
+ }
61
+
62
+ this.wrap = $('<div id="fancybox-thumbs"></div>').addClass(opts.position || 'bottom').appendTo('body');
63
+ this.list = $('<ul>' + list + '</ul>').appendTo(this.wrap);
64
+
65
+ //Load each thumbnail
66
+ $.each(obj.group, function (i) {
67
+ var href = thumbSource( obj.group[ i ] );
68
+
69
+ if (!href) {
70
+ return;
71
+ }
72
+
73
+ $("<img />").load(function () {
74
+ var width = this.width,
75
+ height = this.height,
76
+ widthRatio, heightRatio, parent;
77
+
78
+ if (!that.list || !width || !height) {
79
+ return;
80
+ }
81
+
82
+ //Calculate thumbnail width/height and center it
83
+ widthRatio = width / thumbWidth;
84
+ heightRatio = height / thumbHeight;
85
+
86
+ parent = that.list.children().eq(i).find('a');
87
+
88
+ if (widthRatio >= 1 && heightRatio >= 1) {
89
+ if (widthRatio > heightRatio) {
90
+ width = Math.floor(width / heightRatio);
91
+ height = thumbHeight;
92
+
93
+ } else {
94
+ width = thumbWidth;
95
+ height = Math.floor(height / widthRatio);
96
+ }
97
+ }
98
+
99
+ $(this).css({
100
+ width : width,
101
+ height : height,
102
+ top : Math.floor(thumbHeight / 2 - height / 2),
103
+ left : Math.floor(thumbWidth / 2 - width / 2)
104
+ });
105
+
106
+ parent.width(thumbWidth).height(thumbHeight);
107
+
108
+ $(this).hide().appendTo(parent).fadeIn(300);
109
+
110
+ }).attr('src', href);
111
+ });
112
+
113
+ //Set initial width
114
+ this.width = this.list.children().eq(0).outerWidth(true);
115
+
116
+ this.list.width(this.width * (obj.group.length + 1)).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)));
117
+ },
118
+
119
+ beforeLoad: function (opts, obj) {
120
+ //Remove self if gallery do not have at least two items
121
+ if (obj.group.length < 2) {
122
+ obj.helpers.thumbs = false;
123
+
124
+ return;
125
+ }
126
+
127
+ //Increase bottom margin to give space for thumbs
128
+ obj.margin[ opts.position === 'top' ? 0 : 2 ] += ((opts.height || 50) + 15);
129
+ },
130
+
131
+ afterShow: function (opts, obj) {
132
+ //Check if exists and create or update list
133
+ if (this.list) {
134
+ this.onUpdate(opts, obj);
135
+
136
+ } else {
137
+ this.init(opts, obj);
138
+ }
139
+
140
+ //Set active element
141
+ this.list.children().removeClass('active').eq(obj.index).addClass('active');
142
+ },
143
+
144
+ //Center list
145
+ onUpdate: function (opts, obj) {
146
+ if (this.list) {
147
+ this.list.stop(true).animate({
148
+ 'left': Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5))
149
+ }, 150);
150
+ }
151
+ },
152
+
153
+ beforeClose: function () {
154
+ if (this.wrap) {
155
+ this.wrap.remove();
156
+ }
157
+
158
+ this.wrap = null;
159
+ this.list = null;
160
+ this.width = 0;
161
+ }
162
+ }
163
+
164
+ }(jQuery));
@@ -0,0 +1,1912 @@
1
+ /*!
2
+ * fancyBox - jQuery Plugin
3
+ * version: 2.1.0 (Mon, 20 Aug 2012)
4
+ * @requires jQuery v1.6 or later
5
+ *
6
+ * Examples at http://fancyapps.com/fancybox/
7
+ * License: www.fancyapps.com/fancybox/#license
8
+ *
9
+ * Copyright 2012 Janis Skarnelis - janis@fancyapps.com
10
+ *
11
+ */
12
+
13
+ (function (window, document, $, undefined) {
14
+ "use strict";
15
+
16
+ var W = $(window),
17
+ D = $(document),
18
+ F = $.fancybox = function () {
19
+ F.open.apply( this, arguments );
20
+ },
21
+ didUpdate = null,
22
+ isTouch = document.createTouch !== undefined,
23
+
24
+ isQuery = function(obj) {
25
+ return obj && obj.hasOwnProperty && obj instanceof $;
26
+ },
27
+ isString = function(str) {
28
+ return str && $.type(str) === "string";
29
+ },
30
+ isPercentage = function(str) {
31
+ return isString(str) && str.indexOf('%') > 0;
32
+ },
33
+ isScrollable = function(el) {
34
+ return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight)));
35
+ },
36
+ getScalar = function(value, dim) {
37
+ var value_ = parseInt(value, 10);
38
+
39
+ if (dim && isPercentage(value)) {
40
+ value_ = F.getViewport()[ dim ] / 100 * value_;
41
+ }
42
+
43
+ return Math.ceil(value_);
44
+ },
45
+ getValue = function(value, dim) {
46
+ return getScalar(value, dim) + 'px';
47
+ };
48
+
49
+ $.extend(F, {
50
+ // The current version of fancyBox
51
+ version: '2.1.0',
52
+
53
+ defaults: {
54
+ padding : 15,
55
+ margin : 20,
56
+
57
+ width : 800,
58
+ height : 600,
59
+ minWidth : 100,
60
+ minHeight : 100,
61
+ maxWidth : 9999,
62
+ maxHeight : 9999,
63
+
64
+ autoSize : true,
65
+ autoHeight : false,
66
+ autoWidth : false,
67
+
68
+ autoResize : !isTouch,
69
+ autoCenter : !isTouch,
70
+ fitToView : true,
71
+ aspectRatio : false,
72
+ topRatio : 0.5,
73
+ leftRatio : 0.5,
74
+
75
+ scrolling : 'auto', // 'auto', 'yes' or 'no'
76
+ wrapCSS : '',
77
+
78
+ arrows : true,
79
+ closeBtn : true,
80
+ closeClick : false,
81
+ nextClick : false,
82
+ mouseWheel : true,
83
+ autoPlay : false,
84
+ playSpeed : 3000,
85
+ preload : 3,
86
+ modal : false,
87
+ loop : true,
88
+
89
+ ajax : {
90
+ dataType : 'html',
91
+ headers : { 'X-fancyBox': true }
92
+ },
93
+ iframe : {
94
+ scrolling : 'auto',
95
+ preload : true
96
+ },
97
+ swf : {
98
+ wmode: 'transparent',
99
+ allowfullscreen : 'true',
100
+ allowscriptaccess : 'always'
101
+ },
102
+
103
+ keys : {
104
+ next : {
105
+ 13 : 'left', // enter
106
+ 34 : 'up', // page down
107
+ 39 : 'left', // right arrow
108
+ 40 : 'up' // down arrow
109
+ },
110
+ prev : {
111
+ 8 : 'right', // backspace
112
+ 33 : 'down', // page up
113
+ 37 : 'right', // left arrow
114
+ 38 : 'down' // up arrow
115
+ },
116
+ close : [27], // escape key
117
+ play : [32], // space - start/stop slideshow
118
+ toggle : [70] // letter "f" - toggle fullscreen
119
+ },
120
+
121
+ direction : {
122
+ next : 'left',
123
+ prev : 'right'
124
+ },
125
+
126
+ scrollOutside : true,
127
+
128
+ // Override some properties
129
+ index : 0,
130
+ type : null,
131
+ href : null,
132
+ content : null,
133
+ title : null,
134
+
135
+ // HTML templates
136
+ tpl: {
137
+ wrap : '<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>',
138
+ image : '<img class="fancybox-image" src="{href}" alt="" />',
139
+ iframe : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0"' + ($.browser.msie ? ' allowtransparency="true"' : '') + '></iframe>',
140
+ error : '<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',
141
+ closeBtn : '<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>',
142
+ next : '<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>',
143
+ prev : '<a title="Previous" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>'
144
+ },
145
+
146
+ // Properties for each animation type
147
+ // Opening fancyBox
148
+ openEffect : 'fade', // 'elastic', 'fade' or 'none'
149
+ openSpeed : 250,
150
+ openEasing : 'swing',
151
+ openOpacity : true,
152
+ openMethod : 'zoomIn',
153
+
154
+ // Closing fancyBox
155
+ closeEffect : 'fade', // 'elastic', 'fade' or 'none'
156
+ closeSpeed : 250,
157
+ closeEasing : 'swing',
158
+ closeOpacity : true,
159
+ closeMethod : 'zoomOut',
160
+
161
+ // Changing next gallery item
162
+ nextEffect : 'elastic', // 'elastic', 'fade' or 'none'
163
+ nextSpeed : 250,
164
+ nextEasing : 'swing',
165
+ nextMethod : 'changeIn',
166
+
167
+ // Changing previous gallery item
168
+ prevEffect : 'elastic', // 'elastic', 'fade' or 'none'
169
+ prevSpeed : 250,
170
+ prevEasing : 'swing',
171
+ prevMethod : 'changeOut',
172
+
173
+ // Enabled helpers
174
+ helpers : {
175
+ overlay : {
176
+ closeClick : true,
177
+ speedOut : 200,
178
+ showEarly : true,
179
+ css : {}
180
+ },
181
+ title : {
182
+ type : 'float' // 'float', 'inside', 'outside' or 'over'
183
+ }
184
+ },
185
+
186
+ // Callbacks
187
+ onCancel : $.noop, // If canceling
188
+ beforeLoad : $.noop, // Before loading
189
+ afterLoad : $.noop, // After loading
190
+ beforeShow : $.noop, // Before changing in current item
191
+ afterShow : $.noop, // After opening
192
+ beforeChange : $.noop, // Before changing gallery item
193
+ beforeClose : $.noop, // Before closing
194
+ afterClose : $.noop // After closing
195
+ },
196
+
197
+ //Current state
198
+ group : {}, // Selected group
199
+ opts : {}, // Group options
200
+ previous : null, // Previous element
201
+ coming : null, // Element being loaded
202
+ current : null, // Currently loaded element
203
+ isActive : false, // Is activated
204
+ isOpen : false, // Is currently open
205
+ isOpened : false, // Have been fully opened at least once
206
+
207
+ wrap : null,
208
+ skin : null,
209
+ outer : null,
210
+ inner : null,
211
+
212
+ player : {
213
+ timer : null,
214
+ isActive : false
215
+ },
216
+
217
+ // Loaders
218
+ ajaxLoad : null,
219
+ imgPreload : null,
220
+
221
+ // Some collections
222
+ transitions : {},
223
+ helpers : {},
224
+
225
+ /*
226
+ * Static methods
227
+ */
228
+
229
+ open: function (group, opts) {
230
+ if (!group) {
231
+ return;
232
+ }
233
+
234
+ if (!$.isPlainObject(opts)) {
235
+ opts = {};
236
+ }
237
+
238
+ // Close if already active
239
+ if (false === F.close(true)) {
240
+ return;
241
+ }
242
+
243
+ // Normalize group
244
+ if (!$.isArray(group)) {
245
+ group = isQuery(group) ? $(group).get() : [group];
246
+ }
247
+
248
+ // Recheck if the type of each element is `object` and set content type (image, ajax, etc)
249
+ $.each(group, function(i, element) {
250
+ var obj = {},
251
+ href,
252
+ title,
253
+ content,
254
+ type,
255
+ rez,
256
+ hrefParts,
257
+ selector;
258
+
259
+ if ($.type(element) === "object") {
260
+ // Check if is DOM element
261
+ if (element.nodeType) {
262
+ element = $(element);
263
+ }
264
+
265
+ if (isQuery(element)) {
266
+ obj = {
267
+ href : element.attr('href'),
268
+ title : element.attr('title'),
269
+ isDom : true,
270
+ element : element
271
+ };
272
+
273
+ if ($.metadata) {
274
+ $.extend(true, obj, element.metadata());
275
+ }
276
+
277
+ } else {
278
+ obj = element;
279
+ }
280
+ }
281
+
282
+ href = opts.href || obj.href || (isString(element) ? element : null);
283
+ title = opts.title !== undefined ? opts.title : obj.title || '';
284
+
285
+ content = opts.content || obj.content;
286
+ type = content ? 'html' : (opts.type || obj.type);
287
+
288
+ if (!type && obj.isDom) {
289
+ type = element.data('fancybox-type');
290
+
291
+ if (!type) {
292
+ rez = element.prop('class').match(/fancybox\.(\w+)/);
293
+ type = rez ? rez[1] : null;
294
+ }
295
+ }
296
+
297
+ if (isString(href)) {
298
+ // Try to guess the content type
299
+ if (!type) {
300
+ if (F.isImage(href)) {
301
+ type = 'image';
302
+
303
+ } else if (F.isSWF(href)) {
304
+ type = 'swf';
305
+
306
+ } else if (href.charAt(0) === '#') {
307
+ type = 'inline';
308
+
309
+ } else if (isString(element)) {
310
+ type = 'html';
311
+ content = element;
312
+ }
313
+ }
314
+
315
+ // Split url into two pieces with source url and content selector, e.g,
316
+ // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id"
317
+ if (type === 'ajax') {
318
+ hrefParts = href.split(/\s+/, 2);
319
+ href = hrefParts.shift();
320
+ selector = hrefParts.shift();
321
+ }
322
+ }
323
+
324
+ if (!content) {
325
+ if (type === 'inline') {
326
+ if (href) {
327
+ content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7
328
+
329
+ } else if (obj.isDom) {
330
+ content = element;
331
+ }
332
+
333
+ } else if (type === 'html') {
334
+ content = href;
335
+
336
+ } else if (!type && !href && obj.isDom) {
337
+ type = 'inline';
338
+ content = element;
339
+ }
340
+ }
341
+
342
+ $.extend(obj, {
343
+ href : href,
344
+ type : type,
345
+ content : content,
346
+ title : title,
347
+ selector : selector
348
+ });
349
+
350
+ group[ i ] = obj;
351
+ });
352
+
353
+ // Extend the defaults
354
+ F.opts = $.extend(true, {}, F.defaults, opts);
355
+
356
+ // All options are merged recursive except keys
357
+ if (opts.keys !== undefined) {
358
+ F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false;
359
+ }
360
+
361
+ F.group = group;
362
+
363
+ return F._start(F.opts.index);
364
+ },
365
+
366
+ // Cancel image loading or abort ajax request
367
+ cancel: function () {
368
+ var coming = F.coming;
369
+
370
+ if (!coming || false === F.trigger('onCancel')) {
371
+ return;
372
+ }
373
+
374
+ F.hideLoading();
375
+
376
+ if (F.ajaxLoad) {
377
+ F.ajaxLoad.abort();
378
+ }
379
+
380
+ F.ajaxLoad = null;
381
+
382
+ if (F.imgPreload) {
383
+ F.imgPreload.onload = F.imgPreload.onerror = null;
384
+ }
385
+
386
+ // If the first item has been canceled, then clear everything
387
+ if (coming.wrap) {
388
+ coming.wrap.stop(true).trigger('onReset').remove();
389
+ }
390
+
391
+ if (!F.current) {
392
+ F.trigger('afterClose');
393
+ }
394
+
395
+ F.coming = null;
396
+ },
397
+
398
+ // Start closing animation if is open; remove immediately if opening/closing
399
+ close: function (immediately) {
400
+ F.cancel();
401
+
402
+ if (false === F.trigger('beforeClose')) {
403
+ return;
404
+ }
405
+
406
+ F.unbindEvents();
407
+
408
+ if (!F.isOpen || immediately === true) {
409
+ $('.fancybox-wrap').stop(true).trigger('onReset').remove();
410
+
411
+ F._afterZoomOut();
412
+
413
+ } else {
414
+ F.isOpen = F.isOpened = false;
415
+ F.isClosing = true;
416
+
417
+ $('.fancybox-item, .fancybox-nav').remove();
418
+
419
+ F.wrap.stop(true, true).removeClass('fancybox-opened');
420
+
421
+ if (F.wrap.css('position') === 'fixed') {
422
+ F.wrap.css(F._getPosition( true ));
423
+ }
424
+
425
+ F.transitions[ F.current.closeMethod ]();
426
+ }
427
+ },
428
+
429
+ // Manage slideshow:
430
+ // $.fancybox.play(); - toggle slideshow
431
+ // $.fancybox.play( true ); - start
432
+ // $.fancybox.play( false ); - stop
433
+ play: function ( action ) {
434
+ var clear = function () {
435
+ clearTimeout(F.player.timer);
436
+ },
437
+ set = function () {
438
+ clear();
439
+
440
+ if (F.current && F.player.isActive) {
441
+ F.player.timer = setTimeout(F.next, F.current.playSpeed);
442
+ }
443
+ },
444
+ stop = function () {
445
+ clear();
446
+
447
+ $('body').unbind('.player');
448
+
449
+ F.player.isActive = false;
450
+
451
+ F.trigger('onPlayEnd');
452
+ },
453
+ start = function () {
454
+ if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {
455
+ F.player.isActive = true;
456
+
457
+ $('body').bind({
458
+ 'afterShow.player onUpdate.player' : set,
459
+ 'onCancel.player beforeClose.player' : stop,
460
+ 'beforeLoad.player' : clear
461
+ });
462
+
463
+ set();
464
+
465
+ F.trigger('onPlayStart');
466
+ }
467
+ };
468
+
469
+ if (action === true || (!F.player.isActive && action !== false)) {
470
+ start();
471
+ } else {
472
+ stop();
473
+ }
474
+ },
475
+
476
+ // Navigate to next gallery item
477
+ next: function ( direction ) {
478
+ var current = F.current;
479
+
480
+ if (current) {
481
+ if (!isString(direction)) {
482
+ direction = current.direction.next;
483
+ }
484
+
485
+ F.jumpto(current.index + 1, direction, 'next');
486
+ }
487
+ },
488
+
489
+ // Navigate to previous gallery item
490
+ prev: function ( direction ) {
491
+ var current = F.current;
492
+
493
+ if (current) {
494
+ if (!isString(direction)) {
495
+ direction = current.direction.prev;
496
+ }
497
+
498
+ F.jumpto(current.index - 1, direction, 'prev');
499
+ }
500
+ },
501
+
502
+ // Navigate to gallery item by index
503
+ jumpto: function ( index, direction, router ) {
504
+ var current = F.current;
505
+
506
+ if (!current) {
507
+ return;
508
+ }
509
+
510
+ index = getScalar(index);
511
+
512
+ F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ];
513
+ F.router = router || 'jumpto';
514
+
515
+ if (current.loop) {
516
+ if (index < 0) {
517
+ index = current.group.length + (index % current.group.length);
518
+ }
519
+
520
+ index = index % current.group.length;
521
+ }
522
+
523
+ if (current.group[ index ] !== undefined) {
524
+ F.cancel();
525
+
526
+ F._start(index);
527
+ }
528
+ },
529
+
530
+ // Center inside viewport and toggle position type to fixed or absolute if needed
531
+ reposition: function (e, onlyAbsolute) {
532
+ var pos;
533
+
534
+ if (F.isOpen) {
535
+ pos = F._getPosition(onlyAbsolute);
536
+
537
+ if (e && e.type === 'scroll') {
538
+ delete pos.position;
539
+
540
+ F.wrap.stop(true, true).animate(pos, 200);
541
+
542
+ } else {
543
+ F.wrap.css(pos);
544
+ }
545
+ }
546
+ },
547
+
548
+ update: function (e) {
549
+ var type = (e && e.type),
550
+ anyway = !type || type === 'orientationchange';
551
+
552
+ if (anyway) {
553
+ clearTimeout(didUpdate);
554
+
555
+ didUpdate = null;
556
+ }
557
+
558
+ if (!F.isOpen || didUpdate) {
559
+ return;
560
+ }
561
+
562
+ // Help browser to restore document dimensions
563
+ if (anyway || isTouch) {
564
+ F.wrap.removeAttr('style').addClass('fancybox-tmp');
565
+
566
+ F.trigger('onUpdate');
567
+ }
568
+
569
+ didUpdate = setTimeout(function() {
570
+ var current = F.current;
571
+
572
+ if (!current) {
573
+ return;
574
+ }
575
+
576
+ F.wrap.removeClass('fancybox-tmp');
577
+
578
+ if (type !== 'scroll') {
579
+ F._setDimension();
580
+ }
581
+
582
+ if (!(type === 'scroll' && current.canShrink)) {
583
+ F.reposition(e);
584
+ }
585
+
586
+ F.trigger('onUpdate');
587
+
588
+ didUpdate = null;
589
+
590
+ }, (isTouch ? 500 : (anyway ? 20 : 300)));
591
+ },
592
+
593
+ // Shrink content to fit inside viewport or restore if resized
594
+ toggle: function ( action ) {
595
+ if (F.isOpen) {
596
+ F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView;
597
+
598
+ F.update();
599
+ }
600
+ },
601
+
602
+ hideLoading: function () {
603
+ D.unbind('keypress.fb');
604
+
605
+ $('#fancybox-loading').remove();
606
+ },
607
+
608
+ showLoading: function () {
609
+ var el, viewport;
610
+
611
+ F.hideLoading();
612
+
613
+ // If user will press the escape-button, the request will be canceled
614
+ D.bind('keypress.fb', function(e) {
615
+ if ((e.which || e.keyCode) === 27) {
616
+ e.preventDefault();
617
+ F.cancel();
618
+ }
619
+ });
620
+
621
+ el = $('<div id="fancybox-loading"><div></div></div>').click(F.cancel).appendTo('body');
622
+
623
+ if (!F.defaults.fixed) {
624
+ viewport = F.getViewport();
625
+
626
+ el.css({
627
+ position : 'absolute',
628
+ top : (viewport.h * 0.5) + viewport.y,
629
+ left : (viewport.w * 0.5) + viewport.x
630
+ });
631
+ }
632
+ },
633
+
634
+ getViewport: function () {
635
+ var lock = F.current ? F.current.locked : false,
636
+ rez = {
637
+ x: W.scrollLeft(),
638
+ y: W.scrollTop()
639
+ };
640
+
641
+ if (lock) {
642
+ rez.w = lock[0].clientWidth;
643
+ rez.h = lock[0].clientHeight;
644
+
645
+ } else {
646
+ // See http://bugs.jquery.com/ticket/6724
647
+ rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width();
648
+ rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height();
649
+ }
650
+
651
+ return rez;
652
+ },
653
+
654
+ // Unbind the keyboard / clicking actions
655
+ unbindEvents: function () {
656
+ if (F.wrap && isQuery(F.wrap)) {
657
+ F.wrap.unbind('.fb');
658
+ }
659
+
660
+ D.unbind('.fb');
661
+ W.unbind('.fb');
662
+ },
663
+
664
+ bindEvents: function () {
665
+ var current = F.current,
666
+ keys;
667
+
668
+ if (!current) {
669
+ return;
670
+ }
671
+
672
+ // Changing document height on iOS devices triggers a 'resize' event,
673
+ // that can change document height... repeating infinitely
674
+ W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb' ) + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update);
675
+
676
+ keys = current.keys;
677
+
678
+ if (keys) {
679
+ D.bind('keydown.fb', function (e) {
680
+ var code = e.which || e.keyCode,
681
+ target = e.target || e.srcElement;
682
+
683
+ // Ignore key combinations and key events within form elements
684
+ if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) {
685
+ $.each(keys, function(i, val) {
686
+ if (current.group.length > 1 && val[ code ] !== undefined) {
687
+ F[ i ]( val[ code ] );
688
+
689
+ e.preventDefault();
690
+ return false;
691
+ }
692
+
693
+ if ($.inArray(code, val) > -1) {
694
+ F[ i ] ();
695
+
696
+ e.preventDefault();
697
+ return false;
698
+ }
699
+ });
700
+ }
701
+ });
702
+ }
703
+
704
+ if ($.fn.mousewheel && current.mouseWheel) {
705
+ F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) {
706
+ var target = e.target || null,
707
+ parent = $(target),
708
+ canScroll = false;
709
+
710
+ while (parent.length) {
711
+ if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) {
712
+ break;
713
+ }
714
+
715
+ canScroll = isScrollable( parent[0] );
716
+ parent = $(parent).parent();
717
+ }
718
+
719
+ if (delta !== 0 && !canScroll) {
720
+ if (F.group.length > 1 && !current.canShrink) {
721
+ if (deltaY > 0 || deltaX > 0) {
722
+ F.prev( deltaY > 0 ? 'down' : 'left' );
723
+
724
+ } else if (deltaY < 0 || deltaX < 0) {
725
+ F.next( deltaY < 0 ? 'up' : 'right' );
726
+ }
727
+
728
+ e.preventDefault();
729
+ }
730
+ }
731
+ });
732
+ }
733
+ },
734
+
735
+ trigger: function (event, o) {
736
+ var ret, obj = o || F.coming || F.current;
737
+
738
+ if (!obj) {
739
+ return;
740
+ }
741
+
742
+ if ($.isFunction( obj[event] )) {
743
+ ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));
744
+ }
745
+
746
+ if (ret === false) {
747
+ return false;
748
+ }
749
+
750
+ if (event === 'onCancel' && !F.isOpened) {
751
+ F.isActive = false;
752
+ }
753
+
754
+ if (obj.helpers) {
755
+ $.each(obj.helpers, function (helper, opts) {
756
+ if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) {
757
+ F.helpers[helper][event](opts, obj);
758
+ }
759
+ });
760
+ }
761
+
762
+ $.event.trigger(event + '.fb');
763
+ },
764
+
765
+ isImage: function (str) {
766
+ return isString(str) && str.match(/\.(jp(e|g|eg)|gif|png|bmp|webp)((\?|#).*)?$/i);
767
+ },
768
+
769
+ isSWF: function (str) {
770
+ return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i);
771
+ },
772
+
773
+ _start: function (index) {
774
+ var coming = {},
775
+ obj,
776
+ href,
777
+ type,
778
+ margin,
779
+ padding;
780
+
781
+ index = getScalar( index );
782
+ obj = F.group[ index ] || null;
783
+
784
+ if (!obj) {
785
+ return false;
786
+ }
787
+
788
+ coming = $.extend(true, {}, F.opts, obj);
789
+
790
+ // Convert margin and padding properties to array - top, right, bottom, left
791
+ margin = coming.margin;
792
+ padding = coming.padding;
793
+
794
+ if ($.type(margin) === 'number') {
795
+ coming.margin = [margin, margin, margin, margin];
796
+ }
797
+
798
+ if ($.type(padding) === 'number') {
799
+ coming.padding = [padding, padding, padding, padding];
800
+ }
801
+
802
+ // 'modal' propery is just a shortcut
803
+ if (coming.modal) {
804
+ $.extend(true, coming, {
805
+ closeBtn : false,
806
+ closeClick : false,
807
+ nextClick : false,
808
+ arrows : false,
809
+ mouseWheel : false,
810
+ keys : null,
811
+ helpers: {
812
+ overlay : {
813
+ closeClick : false
814
+ }
815
+ }
816
+ });
817
+ }
818
+
819
+ // 'autoSize' property is a shortcut, too
820
+ if (coming.autoSize) {
821
+ coming.autoWidth = coming.autoHeight = true;
822
+ }
823
+
824
+ if (coming.width === 'auto') {
825
+ coming.autoWidth = true;
826
+ }
827
+
828
+ if (coming.height === 'auto') {
829
+ coming.autoHeight = true;
830
+ }
831
+
832
+ /*
833
+ * Add reference to the group, so it`s possible to access from callbacks, example:
834
+ * afterLoad : function() {
835
+ * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');
836
+ * }
837
+ */
838
+
839
+ coming.group = F.group;
840
+ coming.index = index;
841
+
842
+ // Give a chance for callback or helpers to update coming item (type, title, etc)
843
+ F.coming = coming;
844
+
845
+ if (false === F.trigger('beforeLoad')) {
846
+ F.coming = null;
847
+
848
+ return;
849
+ }
850
+
851
+ type = coming.type;
852
+ href = coming.href;
853
+
854
+ if (!type) {
855
+ F.coming = null;
856
+
857
+ //If we can not determine content type then drop silently or display next/prev item if looping through gallery
858
+ if (F.current && F.router && F.router !== 'jumpto') {
859
+ F.current.index = index;
860
+
861
+ return F[ F.router ]( F.direction );
862
+ }
863
+
864
+ return false;
865
+ }
866
+
867
+ F.isActive = true;
868
+
869
+ if (type === 'image' || type === 'swf') {
870
+ coming.autoHeight = coming.autoWidth = false;
871
+ coming.scrolling = 'visible';
872
+ }
873
+
874
+ if (type === 'image') {
875
+ coming.aspectRatio = true;
876
+ }
877
+
878
+ if (type === 'iframe' && isTouch) {
879
+ coming.scrolling = 'scroll';
880
+ }
881
+
882
+ // Build the neccessary markup
883
+ coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent );
884
+
885
+ $.extend(coming, {
886
+ skin : $('.fancybox-skin', coming.wrap),
887
+ outer : $('.fancybox-outer', coming.wrap),
888
+ inner : $('.fancybox-inner', coming.wrap)
889
+ });
890
+
891
+ $.each(["Top", "Right", "Bottom", "Left"], function(i, v) {
892
+ coming.skin.css('padding' + v, getValue(coming.padding[ i ]));
893
+ });
894
+
895
+ F.trigger('onReady');
896
+
897
+ // Check before try to load; 'inline' and 'html' types need content, others - href
898
+ if (type === 'inline' || type === 'html') {
899
+ if (!coming.content || !coming.content.length) {
900
+ return F._error( 'content' );
901
+ }
902
+
903
+ } else if (!href) {
904
+ return F._error( 'href' );
905
+ }
906
+
907
+ if (type === 'image') {
908
+ F._loadImage();
909
+
910
+ } else if (type === 'ajax') {
911
+ F._loadAjax();
912
+
913
+ } else if (type === 'iframe') {
914
+ F._loadIframe();
915
+
916
+ } else {
917
+ F._afterLoad();
918
+ }
919
+ },
920
+
921
+ _error: function ( type ) {
922
+ $.extend(F.coming, {
923
+ type : 'html',
924
+ autoWidth : true,
925
+ autoHeight : true,
926
+ minWidth : 0,
927
+ minHeight : 0,
928
+ scrolling : 'no',
929
+ hasError : type,
930
+ content : F.coming.tpl.error
931
+ });
932
+
933
+ F._afterLoad();
934
+ },
935
+
936
+ _loadImage: function () {
937
+ // Reset preload image so it is later possible to check "complete" property
938
+ var img = F.imgPreload = new Image();
939
+
940
+ img.onload = function () {
941
+ this.onload = this.onerror = null;
942
+
943
+ F.coming.width = this.width;
944
+ F.coming.height = this.height;
945
+
946
+ F._afterLoad();
947
+ };
948
+
949
+ img.onerror = function () {
950
+ this.onload = this.onerror = null;
951
+
952
+ F._error( 'image' );
953
+ };
954
+
955
+ img.src = F.coming.href;
956
+
957
+ if (img.complete === undefined || !img.complete) {
958
+ F.showLoading();
959
+ }
960
+ },
961
+
962
+ _loadAjax: function () {
963
+ var coming = F.coming;
964
+
965
+ F.showLoading();
966
+
967
+ F.ajaxLoad = $.ajax($.extend({}, coming.ajax, {
968
+ url: coming.href,
969
+ error: function (jqXHR, textStatus) {
970
+ if (F.coming && textStatus !== 'abort') {
971
+ F._error( 'ajax', jqXHR );
972
+
973
+ } else {
974
+ F.hideLoading();
975
+ }
976
+ },
977
+ success: function (data, textStatus) {
978
+ if (textStatus === 'success') {
979
+ coming.content = data;
980
+
981
+ F._afterLoad();
982
+ }
983
+ }
984
+ }));
985
+ },
986
+
987
+ _loadIframe: function() {
988
+ var coming = F.coming,
989
+ iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime()))
990
+ .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling)
991
+ .attr('src', coming.href);
992
+
993
+ // This helps IE
994
+ $(coming.wrap).bind('onReset', function () {
995
+ try {
996
+ $(this).find('iframe').hide().attr('src', '//about:blank').end().empty();
997
+ } catch (e) {}
998
+ });
999
+
1000
+ if (coming.iframe.preload) {
1001
+ F.showLoading();
1002
+
1003
+ iframe.one('load', function() {
1004
+ $(this).data('ready', 1);
1005
+
1006
+ // iOS will lose scrolling if we resize
1007
+ if (!isTouch) {
1008
+ $(this).bind('load.fb', F.update);
1009
+ }
1010
+
1011
+ // Without this trick:
1012
+ // - iframe won't scroll on iOS devices
1013
+ // - IE7 sometimes displays empty iframe
1014
+ $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show();
1015
+
1016
+ F._afterLoad();
1017
+ });
1018
+ }
1019
+
1020
+ coming.content = iframe.appendTo( coming.inner );
1021
+
1022
+ if (!coming.iframe.preload) {
1023
+ F._afterLoad();
1024
+ }
1025
+ },
1026
+
1027
+ _preloadImages: function() {
1028
+ var group = F.group,
1029
+ current = F.current,
1030
+ len = group.length,
1031
+ cnt = current.preload ? Math.min(current.preload, len - 1) : 0,
1032
+ item,
1033
+ i;
1034
+
1035
+ for (i = 1; i <= cnt; i += 1) {
1036
+ item = group[ (current.index + i ) % len ];
1037
+
1038
+ if (item.type === 'image' && item.href) {
1039
+ new Image().src = item.href;
1040
+ }
1041
+ }
1042
+ },
1043
+
1044
+ _afterLoad: function () {
1045
+ var coming = F.coming,
1046
+ previous = F.current,
1047
+ placeholder = 'fancybox-placeholder',
1048
+ current,
1049
+ content,
1050
+ type,
1051
+ scrolling,
1052
+ href,
1053
+ embed;
1054
+
1055
+ F.hideLoading();
1056
+
1057
+ if (!coming || F.isActive === false) {
1058
+ return;
1059
+ }
1060
+
1061
+ if (false === F.trigger('afterLoad', coming, previous)) {
1062
+ coming.wrap.stop(true).trigger('onReset').remove();
1063
+
1064
+ F.coming = null;
1065
+
1066
+ return;
1067
+ }
1068
+
1069
+ if (previous) {
1070
+ F.trigger('beforeChange', previous);
1071
+
1072
+ previous.wrap.stop(true).removeClass('fancybox-opened')
1073
+ .find('.fancybox-item, .fancybox-nav')
1074
+ .remove();
1075
+
1076
+ if (previous.wrap.css('position') === 'fixed') {
1077
+ previous.wrap.css(F._getPosition( true ));
1078
+ }
1079
+ }
1080
+
1081
+ F.unbindEvents();
1082
+
1083
+ current = coming;
1084
+ content = coming.content;
1085
+ type = coming.type;
1086
+ scrolling = coming.scrolling;
1087
+
1088
+ $.extend(F, {
1089
+ wrap : current.wrap,
1090
+ skin : current.skin,
1091
+ outer : current.outer,
1092
+ inner : current.inner,
1093
+ current : current,
1094
+ previous : previous
1095
+ });
1096
+
1097
+ href = current.href;
1098
+
1099
+ switch (type) {
1100
+ case 'inline':
1101
+ case 'ajax':
1102
+ case 'html':
1103
+ if (current.selector) {
1104
+ content = $('<div>').html(content).find(current.selector);
1105
+
1106
+ } else if (isQuery(content)) {
1107
+ if (!content.data(placeholder)) {
1108
+ content.data(placeholder, $('<div class="' + placeholder + '"></div>').insertAfter( content ).hide() );
1109
+ }
1110
+
1111
+ content = content.show().detach();
1112
+
1113
+ current.wrap.bind('onReset', function () {
1114
+ if ($(this).find(content).length) {
1115
+ content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false);
1116
+ }
1117
+ });
1118
+ }
1119
+ break;
1120
+
1121
+ case 'image':
1122
+ content = current.tpl.image.replace('{href}', href);
1123
+ break;
1124
+
1125
+ case 'swf':
1126
+ content = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="' + href + '"></param>';
1127
+ embed = '';
1128
+
1129
+ $.each(current.swf, function(name, val) {
1130
+ content += '<param name="' + name + '" value="' + val + '"></param>';
1131
+ embed += ' ' + name + '="' + val + '"';
1132
+ });
1133
+
1134
+ content += '<embed src="' + href + '" type="application/x-shockwave-flash" width="100%" height="100%"' + embed + '></embed></object>';
1135
+ break;
1136
+ }
1137
+
1138
+ if (!(isQuery(content) && content.parent().is(current.inner))) {
1139
+ current.inner.append( content );
1140
+ }
1141
+
1142
+ // Give a chance for helpers or callbacks to update elements
1143
+ F.trigger('beforeShow');
1144
+
1145
+ // Set scrolling before calculating dimensions
1146
+ current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling));
1147
+
1148
+ // Set initial dimensions and start position
1149
+ F._setDimension();
1150
+
1151
+ current.wrap.removeClass('fancybox-tmp');
1152
+
1153
+ current.pos = $.extend({}, current.dim, F._getPosition( true ));
1154
+
1155
+ F.isOpen = false;
1156
+ F.coming = null;
1157
+
1158
+ F.bindEvents();
1159
+
1160
+ if (!F.isOpened) {
1161
+ $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove();
1162
+
1163
+ } else if (previous.prevMethod) {
1164
+ F.transitions[ previous.prevMethod ]();
1165
+ }
1166
+
1167
+ F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ]();
1168
+
1169
+ F._preloadImages();
1170
+ },
1171
+
1172
+ _setDimension: function () {
1173
+ var viewport = F.getViewport(),
1174
+ steps = 0,
1175
+ canShrink = false,
1176
+ canExpand = false,
1177
+ wrap = F.wrap,
1178
+ skin = F.skin,
1179
+ inner = F.inner,
1180
+ current = F.current,
1181
+ width = current.width,
1182
+ height = current.height,
1183
+ minWidth = current.minWidth,
1184
+ minHeight = current.minHeight,
1185
+ maxWidth = current.maxWidth,
1186
+ maxHeight = current.maxHeight,
1187
+ scrolling = current.scrolling,
1188
+ scrollOut = current.scrollOutside ? current.scrollbarWidth : 0,
1189
+ margin = current.margin,
1190
+ wMargin = margin[1] + margin[3],
1191
+ hMargin = margin[0] + margin[2],
1192
+ wPadding,
1193
+ hPadding,
1194
+ wSpace,
1195
+ hSpace,
1196
+ origWidth,
1197
+ origHeight,
1198
+ origMaxWidth,
1199
+ origMaxHeight,
1200
+ ratio,
1201
+ width_,
1202
+ height_,
1203
+ maxWidth_,
1204
+ maxHeight_,
1205
+ iframe,
1206
+ body;
1207
+
1208
+ // Reset dimensions so we could re-check actual size
1209
+ wrap.add(skin).add(inner).width('auto').height('auto');
1210
+
1211
+ wPadding = skin.outerWidth(true) - skin.width();
1212
+ hPadding = skin.outerHeight(true) - skin.height();
1213
+
1214
+ // Any space between content and viewport (margin, padding, border, title)
1215
+ wSpace = wMargin + wPadding;
1216
+ hSpace = hMargin + hPadding;
1217
+
1218
+ origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width;
1219
+ origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height;
1220
+
1221
+ if (current.type === 'iframe') {
1222
+ iframe = current.content;
1223
+
1224
+ if (current.autoHeight && iframe.data('ready') === 1) {
1225
+ try {
1226
+ if (iframe[0].contentWindow.document.location) {
1227
+ inner.width( origWidth ).height(9999);
1228
+
1229
+ body = iframe.contents().find('body');
1230
+
1231
+ if (scrollOut) {
1232
+ body.css('overflow-x', 'hidden');
1233
+ }
1234
+
1235
+ origHeight = body.height();
1236
+ }
1237
+
1238
+ } catch (e) {}
1239
+ }
1240
+
1241
+ } else if (current.autoWidth || current.autoHeight) {
1242
+ inner.addClass( 'fancybox-tmp' );
1243
+
1244
+ // Set width or height in case we need to calculate only one dimension
1245
+ if (!current.autoWidth) {
1246
+ inner.width( origWidth );
1247
+ }
1248
+
1249
+ if (!current.autoHeight) {
1250
+ inner.height( origHeight );
1251
+ }
1252
+
1253
+ if (current.autoWidth) {
1254
+ origWidth = inner.width();
1255
+ }
1256
+
1257
+ if (current.autoHeight) {
1258
+ origHeight = inner.height();
1259
+ }
1260
+
1261
+ inner.removeClass( 'fancybox-tmp' );
1262
+ }
1263
+
1264
+ width = getScalar( origWidth );
1265
+ height = getScalar( origHeight );
1266
+
1267
+ ratio = origWidth / origHeight;
1268
+
1269
+ // Calculations for the content
1270
+ minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth);
1271
+ maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth);
1272
+
1273
+ minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight);
1274
+ maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight);
1275
+
1276
+ // These will be used to determine if wrap can fit in the viewport
1277
+ origMaxWidth = maxWidth;
1278
+ origMaxHeight = maxHeight;
1279
+
1280
+ maxWidth_ = viewport.w - wMargin;
1281
+ maxHeight_ = viewport.h - hMargin;
1282
+
1283
+ if (current.aspectRatio) {
1284
+ if (width > maxWidth) {
1285
+ width = maxWidth;
1286
+ height = width / ratio;
1287
+ }
1288
+
1289
+ if (height > maxHeight) {
1290
+ height = maxHeight;
1291
+ width = height * ratio;
1292
+ }
1293
+
1294
+ if (width < minWidth) {
1295
+ width = minWidth;
1296
+ height = width / ratio;
1297
+ }
1298
+
1299
+ if (height < minHeight) {
1300
+ height = minHeight;
1301
+ width = height * ratio;
1302
+ }
1303
+
1304
+ } else {
1305
+ width = Math.max(minWidth, Math.min(width, maxWidth));
1306
+ height = Math.max(minHeight, Math.min(height, maxHeight));
1307
+ }
1308
+
1309
+ // Try to fit inside viewport (including the title)
1310
+ if (current.fitToView) {
1311
+ maxWidth = Math.min(viewport.w - wSpace, maxWidth);
1312
+ maxHeight = Math.min(viewport.h - hSpace, maxHeight);
1313
+
1314
+ inner.width( getScalar( width ) ).height( getScalar( height ) );
1315
+
1316
+ wrap.width( getScalar( width + wPadding ) );
1317
+
1318
+ // Real wrap dimensions
1319
+ width_ = wrap.width();
1320
+ height_ = wrap.height();
1321
+
1322
+ if (current.aspectRatio) {
1323
+ while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) {
1324
+ if (steps++ > 19) {
1325
+ break;
1326
+ }
1327
+
1328
+ height = Math.max(minHeight, Math.min(maxHeight, height - 10));
1329
+ width = height * ratio;
1330
+
1331
+ if (width < minWidth) {
1332
+ width = minWidth;
1333
+ height = width / ratio;
1334
+ }
1335
+
1336
+ if (width > maxWidth) {
1337
+ width = maxWidth;
1338
+ height = width / ratio;
1339
+ }
1340
+
1341
+ inner.width( getScalar( width ) ).height( getScalar( height ) );
1342
+
1343
+ wrap.width( getScalar( width + wPadding ) );
1344
+
1345
+ width_ = wrap.width();
1346
+ height_ = wrap.height();
1347
+ }
1348
+
1349
+ } else {
1350
+ width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_)));
1351
+ height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_)));
1352
+ }
1353
+ }
1354
+
1355
+ if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) {
1356
+ width += scrollOut;
1357
+ }
1358
+
1359
+ inner.width( getScalar( width ) ).height( getScalar( height ) );
1360
+
1361
+ wrap.width( getScalar( width + wPadding ) );
1362
+
1363
+ width_ = wrap.width();
1364
+ height_ = wrap.height();
1365
+
1366
+ canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight;
1367
+ canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight));
1368
+
1369
+ $.extend(current, {
1370
+ dim : {
1371
+ width : getValue( width_ ),
1372
+ height : getValue( height_ )
1373
+ },
1374
+ origWidth : origWidth,
1375
+ origHeight : origHeight,
1376
+ canShrink : canShrink,
1377
+ canExpand : canExpand,
1378
+ wPadding : wPadding,
1379
+ hPadding : hPadding,
1380
+ wrapSpace : height_ - skin.outerHeight(true),
1381
+ skinSpace : skin.height() - height
1382
+ });
1383
+
1384
+ if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) {
1385
+ inner.height('auto');
1386
+ }
1387
+ },
1388
+
1389
+ _getPosition: function (onlyAbsolute) {
1390
+ var current = F.current,
1391
+ viewport = F.getViewport(),
1392
+ margin = current.margin,
1393
+ width = F.wrap.width() + margin[1] + margin[3],
1394
+ height = F.wrap.height() + margin[0] + margin[2],
1395
+ rez = {
1396
+ position: 'absolute',
1397
+ top : margin[0],
1398
+ left : margin[3]
1399
+ };
1400
+
1401
+ if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) {
1402
+ rez.position = 'fixed';
1403
+
1404
+ } else if (!current.locked) {
1405
+ rez.top += viewport.y;
1406
+ rez.left += viewport.x;
1407
+ }
1408
+
1409
+ rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio)));
1410
+ rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio)));
1411
+
1412
+ return rez;
1413
+ },
1414
+
1415
+ _afterZoomIn: function () {
1416
+ var current = F.current;
1417
+
1418
+ if (!current) {
1419
+ return;
1420
+ }
1421
+
1422
+ F.isOpen = F.isOpened = true;
1423
+
1424
+ F.wrap.addClass('fancybox-opened').css('overflow', 'visible');
1425
+
1426
+ F.reposition();
1427
+
1428
+ // Assign a click event
1429
+ if (current.closeClick || current.nextClick) {
1430
+ F.inner.css('cursor', 'pointer').bind('click.fb', function(e) {
1431
+ if (!$(e.target).is('a') && !$(e.target).parent().is('a')) {
1432
+ F[ current.closeClick ? 'close' : 'next' ]();
1433
+ }
1434
+ });
1435
+ }
1436
+
1437
+ // Create a close button
1438
+ if (current.closeBtn) {
1439
+ $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', F.close);
1440
+ }
1441
+
1442
+ // Create navigation arrows
1443
+ if (current.arrows && F.group.length > 1) {
1444
+ if (current.loop || current.index > 0) {
1445
+ $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev);
1446
+ }
1447
+
1448
+ if (current.loop || current.index < F.group.length - 1) {
1449
+ $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next);
1450
+ }
1451
+ }
1452
+
1453
+ F.trigger('afterShow');
1454
+
1455
+ // Stop the slideshow if this is the last item
1456
+ if (!current.loop && current.index === current.group.length - 1) {
1457
+ F.play( false );
1458
+
1459
+ } else if (F.opts.autoPlay && !F.player.isActive) {
1460
+ F.opts.autoPlay = false;
1461
+
1462
+ F.play();
1463
+ }
1464
+ },
1465
+
1466
+ _afterZoomOut: function () {
1467
+ var current = F.current;
1468
+
1469
+ $('.fancybox-wrap').stop(true).trigger('onReset').remove();
1470
+
1471
+ $.extend(F, {
1472
+ group : {},
1473
+ opts : {},
1474
+ router : false,
1475
+ current : null,
1476
+ isActive : false,
1477
+ isOpened : false,
1478
+ isOpen : false,
1479
+ isClosing : false,
1480
+ wrap : null,
1481
+ skin : null,
1482
+ outer : null,
1483
+ inner : null
1484
+ });
1485
+
1486
+ F.trigger('afterClose', current);
1487
+ }
1488
+ });
1489
+
1490
+ /*
1491
+ * Default transitions
1492
+ */
1493
+
1494
+ F.transitions = {
1495
+ getOrigPosition: function () {
1496
+ var current = F.current,
1497
+ element = current.element,
1498
+ orig = current.orig,
1499
+ pos = {},
1500
+ width = 50,
1501
+ height = 50,
1502
+ hPadding = current.hPadding,
1503
+ wPadding = current.wPadding,
1504
+ viewport = F.getViewport();
1505
+
1506
+ if (!orig && current.isDom && element.is(':visible')) {
1507
+ orig = element.find('img:first');
1508
+
1509
+ if (!orig.length) {
1510
+ orig = element;
1511
+ }
1512
+ }
1513
+
1514
+ if (isQuery(orig)) {
1515
+ pos = orig.offset();
1516
+
1517
+ if (orig.is('img')) {
1518
+ width = orig.outerWidth();
1519
+ height = orig.outerHeight();
1520
+ }
1521
+
1522
+ } else {
1523
+ pos.top = viewport.y + (viewport.h - height) * current.topRatio;
1524
+ pos.left = viewport.x + (viewport.w - width) * current.leftRatio;
1525
+ }
1526
+
1527
+ if (current.locked) {
1528
+ pos.top -= viewport.y;
1529
+ pos.left -= viewport.x;
1530
+ }
1531
+
1532
+ pos = {
1533
+ top : getValue(pos.top - hPadding * current.topRatio),
1534
+ left : getValue(pos.left - wPadding * current.leftRatio),
1535
+ width : getValue(width + wPadding),
1536
+ height : getValue(height + hPadding)
1537
+ };
1538
+
1539
+ return pos;
1540
+ },
1541
+
1542
+ step: function (now, fx) {
1543
+ var ratio,
1544
+ padding,
1545
+ value,
1546
+ prop = fx.prop,
1547
+ current = F.current,
1548
+ wrapSpace = current.wrapSpace,
1549
+ skinSpace = current.skinSpace;
1550
+
1551
+ if (prop === 'width' || prop === 'height') {
1552
+ ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start);
1553
+
1554
+ if (F.isClosing) {
1555
+ ratio = 1 - ratio;
1556
+ }
1557
+
1558
+ padding = prop === 'width' ? current.wPadding : current.hPadding;
1559
+ value = now - padding;
1560
+
1561
+ F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) );
1562
+ F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) );
1563
+ }
1564
+ },
1565
+
1566
+ zoomIn: function () {
1567
+ var current = F.current,
1568
+ startPos = current.pos,
1569
+ effect = current.openEffect,
1570
+ elastic = effect === 'elastic',
1571
+ endPos = $.extend({opacity : 1}, startPos);
1572
+
1573
+ // Remove "position" property that breaks older IE
1574
+ delete endPos.position;
1575
+
1576
+ if (elastic) {
1577
+ startPos = this.getOrigPosition();
1578
+
1579
+ if (current.openOpacity) {
1580
+ startPos.opacity = 0.1;
1581
+ }
1582
+
1583
+ } else if (effect === 'fade') {
1584
+ startPos.opacity = 0.1;
1585
+ }
1586
+
1587
+ F.wrap.css(startPos).animate(endPos, {
1588
+ duration : effect === 'none' ? 0 : current.openSpeed,
1589
+ easing : current.openEasing,
1590
+ step : elastic ? this.step : null,
1591
+ complete : F._afterZoomIn
1592
+ });
1593
+ },
1594
+
1595
+ zoomOut: function () {
1596
+ var current = F.current,
1597
+ effect = current.closeEffect,
1598
+ elastic = effect === 'elastic',
1599
+ endPos = {opacity : 0.1};
1600
+
1601
+ if (elastic) {
1602
+ endPos = this.getOrigPosition();
1603
+
1604
+ if (current.closeOpacity) {
1605
+ endPos.opacity = 0.1;
1606
+ }
1607
+ }
1608
+
1609
+ F.wrap.animate(endPos, {
1610
+ duration : effect === 'none' ? 0 : current.closeSpeed,
1611
+ easing : current.closeEasing,
1612
+ step : elastic ? this.step : null,
1613
+ complete : F._afterZoomOut
1614
+ });
1615
+ },
1616
+
1617
+ changeIn: function () {
1618
+ var current = F.current,
1619
+ effect = current.nextEffect,
1620
+ startPos = current.pos,
1621
+ endPos = { opacity : 1 },
1622
+ direction = F.direction,
1623
+ distance = 200,
1624
+ field;
1625
+
1626
+ startPos.opacity = 0.1;
1627
+
1628
+ if (effect === 'elastic') {
1629
+ field = direction === 'down' || direction === 'up' ? 'top' : 'left';
1630
+
1631
+ if (direction === 'down' || direction === 'right') {
1632
+ startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance);
1633
+ endPos[ field ] = '+=' + distance + 'px';
1634
+
1635
+ } else {
1636
+ startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance);
1637
+ endPos[ field ] = '-=' + distance + 'px';
1638
+ }
1639
+ }
1640
+
1641
+ // Workaround for http://bugs.jquery.com/ticket/12273
1642
+ if (effect === 'none') {
1643
+ F._afterZoomIn();
1644
+
1645
+ } else {
1646
+ F.wrap.css(startPos).animate(endPos, {
1647
+ duration : current.nextSpeed,
1648
+ easing : current.nextEasing,
1649
+ complete : F._afterZoomIn
1650
+ });
1651
+ }
1652
+ },
1653
+
1654
+ changeOut: function () {
1655
+ var previous = F.previous,
1656
+ effect = previous.prevEffect,
1657
+ endPos = { opacity : 0.1 },
1658
+ direction = F.direction,
1659
+ distance = 200;
1660
+
1661
+ if (effect === 'elastic') {
1662
+ endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px';
1663
+ }
1664
+
1665
+ previous.wrap.animate(endPos, {
1666
+ duration : effect === 'none' ? 0 : previous.prevSpeed,
1667
+ easing : previous.prevEasing,
1668
+ complete : function () {
1669
+ $(this).trigger('onReset').remove();
1670
+ }
1671
+ });
1672
+ }
1673
+ };
1674
+
1675
+ /*
1676
+ * Overlay helper
1677
+ */
1678
+
1679
+ F.helpers.overlay = {
1680
+ overlay: null,
1681
+
1682
+ update: function () {
1683
+ var width = '100%', offsetWidth;
1684
+
1685
+ // Reset width/height so it will not mess
1686
+ this.overlay.width(width).height('100%');
1687
+
1688
+ // jQuery does not return reliable result for IE
1689
+ if ($.browser.msie) {
1690
+ offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);
1691
+
1692
+ if (D.width() > offsetWidth) {
1693
+ width = D.width();
1694
+ }
1695
+
1696
+ } else if (D.width() > W.width()) {
1697
+ width = D.width();
1698
+ }
1699
+
1700
+ this.overlay.width(width).height(D.height());
1701
+ },
1702
+
1703
+ // This is where we can manipulate DOM, because later it would cause iframes to reload
1704
+ onReady: function (opts, obj) {
1705
+ $('.fancybox-overlay').stop(true, true);
1706
+
1707
+ if (!this.overlay) {
1708
+ $.extend(this, {
1709
+ overlay : $('<div class="fancybox-overlay"></div>').appendTo( obj.parent ),
1710
+ margin : D.height() > W.height() || $('body').css('overflow-y') === 'scroll' ? $('body').css('margin-right') : false,
1711
+ el : document.all && !document.querySelector ? $('html') : $('body')
1712
+ });
1713
+ }
1714
+
1715
+ if (obj.fixed && !isTouch) {
1716
+ this.overlay.addClass('fancybox-overlay-fixed');
1717
+
1718
+ if (obj.autoCenter) {
1719
+ this.overlay.append( obj.wrap );
1720
+
1721
+ obj.locked = this.overlay;
1722
+ }
1723
+ }
1724
+
1725
+ if (opts.showEarly === true) {
1726
+ this.beforeShow.apply(this, arguments);
1727
+ }
1728
+ },
1729
+
1730
+ beforeShow : function(opts, obj) {
1731
+ var overlay = this.overlay.unbind('.fb').width('auto').height('auto').css( opts.css );
1732
+
1733
+ if (opts.closeClick) {
1734
+ overlay.bind('click.fb', function(e) {
1735
+ if ($(e.target).hasClass('fancybox-overlay')) {
1736
+ F.close();
1737
+ }
1738
+ });
1739
+ }
1740
+
1741
+ if (obj.fixed && !isTouch) {
1742
+ if (obj.locked) {
1743
+ this.el.addClass('fancybox-lock');
1744
+
1745
+ if (this.margin !== false) {
1746
+ $('body').css('margin-right', getScalar( this.margin ) + obj.scrollbarWidth);
1747
+ }
1748
+ }
1749
+
1750
+ } else {
1751
+ this.update();
1752
+ }
1753
+
1754
+ overlay.show();
1755
+ },
1756
+
1757
+ onUpdate : function(opts, obj) {
1758
+ if (!obj.fixed || isTouch) {
1759
+ this.update();
1760
+ }
1761
+ },
1762
+
1763
+ afterClose: function (opts) {
1764
+ var that = this,
1765
+ speed = opts.speedOut || 0;
1766
+
1767
+ // Remove overlay if exists and fancyBox is not opening
1768
+ // (e.g., it is not being open using afterClose callback)
1769
+ if (that.overlay && !F.isActive) {
1770
+ that.overlay.fadeOut(speed || 0, function () {
1771
+ $('body').css('margin-right', that.margin);
1772
+
1773
+ that.el.removeClass('fancybox-lock');
1774
+
1775
+ that.overlay.remove();
1776
+
1777
+ that.overlay = null;
1778
+ });
1779
+ }
1780
+ }
1781
+ };
1782
+
1783
+ /*
1784
+ * Title helper
1785
+ */
1786
+
1787
+ F.helpers.title = {
1788
+ beforeShow: function (opts) {
1789
+ var text = F.current.title,
1790
+ type = opts.type,
1791
+ title,
1792
+ target;
1793
+
1794
+ if (!isString(text) || $.trim(text) === '') {
1795
+ return;
1796
+ }
1797
+
1798
+ title = $('<div class="fancybox-title fancybox-title-' + type + '-wrap">' + text + '</div>');
1799
+
1800
+ switch (type) {
1801
+ case 'inside':
1802
+ target = F.skin;
1803
+ break;
1804
+
1805
+ case 'outside':
1806
+ target = F.wrap;
1807
+ break;
1808
+
1809
+ case 'over':
1810
+ target = F.inner;
1811
+ break;
1812
+
1813
+ default: // 'float'
1814
+ target = F.skin;
1815
+
1816
+ title
1817
+ .appendTo('body')
1818
+ .width(title.width()) //This helps for some browsers
1819
+ .wrapInner('<span class="child"></span>');
1820
+
1821
+ //Increase bottom margin so this title will also fit into viewport
1822
+ F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) );
1823
+ break;
1824
+ }
1825
+
1826
+ if (opts.position === 'top') {
1827
+ title.prependTo(target);
1828
+
1829
+ } else {
1830
+ title.appendTo(target);
1831
+ }
1832
+ }
1833
+ };
1834
+
1835
+ // jQuery plugin initialization
1836
+ $.fn.fancybox = function (options) {
1837
+ var index,
1838
+ that = $(this),
1839
+ selector = this.selector || '',
1840
+ run = function(e) {
1841
+ var what = $(this).blur(), idx = index, relType, relVal;
1842
+
1843
+ if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) {
1844
+ relType = options.groupAttr || 'data-fancybox-group';
1845
+ relVal = what.attr(relType);
1846
+
1847
+ if (!relVal) {
1848
+ relType = 'rel';
1849
+ relVal = what.get(0)[ relType ];
1850
+ }
1851
+
1852
+ if (relVal && relVal !== '' && relVal !== 'nofollow') {
1853
+ what = selector.length ? $(selector) : that;
1854
+ what = what.filter('[' + relType + '="' + relVal + '"]');
1855
+ idx = what.index(this);
1856
+ }
1857
+
1858
+ options.index = idx;
1859
+
1860
+ // Stop an event from bubbling if everything is fine
1861
+ if (F.open(what, options) !== false) {
1862
+ e.preventDefault();
1863
+ }
1864
+ }
1865
+ };
1866
+
1867
+ options = options || {};
1868
+ index = options.index || 0;
1869
+
1870
+ if (!selector || options.live === false) {
1871
+ that.unbind('click.fb-start').bind('click.fb-start', run);
1872
+ } else {
1873
+ D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run);
1874
+ }
1875
+
1876
+ return this;
1877
+ };
1878
+
1879
+ // Tests that need a body at doc ready
1880
+ D.ready(function() {
1881
+ if ( $.scrollbarWidth === undefined ) {
1882
+ // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth
1883
+ $.scrollbarWidth = function() {
1884
+ var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'),
1885
+ child = parent.children(),
1886
+ width = child.innerWidth() - child.height( 99 ).innerWidth();
1887
+
1888
+ parent.remove();
1889
+
1890
+ return width;
1891
+ };
1892
+ }
1893
+
1894
+ if ( $.support.fixedPosition === undefined ) {
1895
+ $.support.fixedPosition = (function() {
1896
+ var elem = $('<div style="position:fixed;top:20px;"></div>').appendTo('body'),
1897
+ fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 );
1898
+
1899
+ elem.remove();
1900
+
1901
+ return fixed;
1902
+ }());
1903
+ }
1904
+
1905
+ $.extend(F.defaults, {
1906
+ scrollbarWidth : $.scrollbarWidth(),
1907
+ fixed : $.support.fixedPosition,
1908
+ parent : $('body')
1909
+ });
1910
+ });
1911
+
1912
+ }(window, document, jQuery));