alula-plugins 0.0.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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in alula-plugins.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Mikko Kokkonen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Alula::Plugins
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'alula-plugins'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install alula-plugins
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/alula/plugins/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Mikko Kokkonen"]
6
+ gem.email = ["mikko@owlforestry.com"]
7
+ gem.description = %q{Plugins for Alula blog}
8
+ gem.summary = %q{Simple, ready to use plugins for Alula blogs.}
9
+ gem.homepage = ""
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "alula-plugins"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Alula::Plugins::VERSION
17
+
18
+ gem.add_dependency 'alula'
19
+ end
@@ -0,0 +1,7 @@
1
+ require "alula/plugins/version"
2
+
3
+ module Alula
4
+ module Plugins
5
+ # Your code goes here...
6
+ end
7
+ end
@@ -0,0 +1,41 @@
1
+ module Alula
2
+ module Plugins
3
+ class Lightbox < Liquid::Tag
4
+ def self.install(options)
5
+ @@options = options
6
+
7
+ # Register custom tag
8
+ Liquid::Template.register_tag('lightbox', Alula::Plugins::Lightbox)
9
+
10
+ # Return path to assets
11
+ File.expand_path(File.join(File.dirname(__FILE__), *%w{.. .. .. plugins lightbox}))
12
+ end
13
+
14
+ def initialize(tag_name, markup, tokens)
15
+ /(?<src>(?:https?:\/\/|\/|\S+\/)\S+)(?<title>\s+.+)/ =~ markup
16
+ /(?:"|')(?<title>[^"']+)?(?:"|')\s+(?:"|')(?<alt>[^"']+)?(?:"|')/ =~ title
17
+
18
+ @name = src
19
+ @title = title
20
+ @alt = alt
21
+ end
22
+
23
+ def render(context)
24
+ asset_path = context.registers[:site].config["asset_path"]
25
+ manifest = context.registers[:site].config["manifest"]
26
+
27
+ original = File.join(asset_path, manifest.assets[File.join("_originals", @name)])
28
+ thumbnail = File.join(asset_path, manifest.assets[File.join("_thumbnails", @name)])
29
+
30
+ # Fetch image size
31
+ img = Magick::Image.read(File.join("public", thumbnail)).first
32
+ width = img.columns
33
+ height = img.rows
34
+
35
+ tag = "<a class=\"fancybox\" rel=\"#{context.environments.first["page"]["id"]}\" href=\"#{original}\">"
36
+ tag += "<img src=\"#{thumbnail}\" alt=\"#{@alt}\" title=\"#{@title}\" width=\"#{width}\" height=\"#{height}\">"
37
+ tag += "</a>"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ module Alula
2
+ module Plugins
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/plugins/.DS_Store ADDED
Binary file
Binary file
@@ -0,0 +1,1414 @@
1
+ /*!
2
+ * fancyBox - jQuery Plugin
3
+ * version: 2.0.5 (21/02/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
+ (function (window, document, $) {
13
+ var W = $(window),
14
+ D = $(document),
15
+ F = $.fancybox = function () {
16
+ F.open.apply( this, arguments );
17
+ },
18
+ didResize = false,
19
+ resizeTimer = null,
20
+ isMobile = typeof document.createTouch !== "undefined";
21
+
22
+ $.extend(F, {
23
+ // The current version of fancyBox
24
+ version: '2.0.5',
25
+
26
+ defaults: {
27
+ padding: 15,
28
+ margin: 20,
29
+
30
+ width: 800,
31
+ height: 600,
32
+ minWidth: 100,
33
+ minHeight: 100,
34
+ maxWidth: 9999,
35
+ maxHeight: 9999,
36
+
37
+ autoSize: true,
38
+ autoResize: !isMobile,
39
+ autoCenter : !isMobile,
40
+ fitToView: true,
41
+ aspectRatio: false,
42
+ topRatio: 0.5,
43
+
44
+ fixed: !($.browser.msie && $.browser.version <= 6) && !isMobile,
45
+ scrolling: 'auto', // 'auto', 'yes' or 'no'
46
+ wrapCSS: 'fancybox-default',
47
+
48
+ arrows: true,
49
+ closeBtn: true,
50
+ closeClick: false,
51
+ nextClick : false,
52
+ mouseWheel: true,
53
+ autoPlay: false,
54
+ playSpeed: 3000,
55
+ preload : 3,
56
+
57
+ modal: false,
58
+ loop: true,
59
+ ajax: { dataType: 'html', headers: { 'X-fancyBox': true } },
60
+ keys: {
61
+ next: [13, 32, 34, 39, 40], // enter, space, page down, right arrow, down arrow
62
+ prev: [8, 33, 37, 38], // backspace, page up, left arrow, up arrow
63
+ close: [27] // escape key
64
+ },
65
+
66
+ // Override some properties
67
+ index: 0,
68
+ type: null,
69
+ href: null,
70
+ content: null,
71
+ title: null,
72
+
73
+ // HTML templates
74
+ tpl: {
75
+ wrap: '<div class="fancybox-wrap"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div>',
76
+ image: '<img class="fancybox-image" src="{href}" alt="" />',
77
+ iframe: '<iframe class="fancybox-iframe" name="fancybox-frame{rnd}" frameborder="0" hspace="0"' + ($.browser.msie ? ' allowtransparency="true"' : '') + '></iframe>',
78
+ swf: '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="wmode" value="transparent" /><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="{href}" /><embed src="{href}" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="100%" height="100%" wmode="transparent"></embed></object>',
79
+ error: '<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',
80
+ closeBtn: '<div title="Close" class="fancybox-item fancybox-close"></div>',
81
+ next: '<a title="Next" class="fancybox-nav fancybox-next"><span></span></a>',
82
+ prev: '<a title="Previous" class="fancybox-nav fancybox-prev"><span></span></a>'
83
+ },
84
+
85
+ // Properties for each animation type
86
+ // Opening fancyBox
87
+ openEffect: 'fade', // 'elastic', 'fade' or 'none'
88
+ openSpeed: 250,
89
+ openEasing: 'swing',
90
+ openOpacity: true,
91
+ openMethod: 'zoomIn',
92
+
93
+ // Closing fancyBox
94
+ closeEffect: 'fade', // 'elastic', 'fade' or 'none'
95
+ closeSpeed: 250,
96
+ closeEasing: 'swing',
97
+ closeOpacity: true,
98
+ closeMethod: 'zoomOut',
99
+
100
+ // Changing next gallery item
101
+ nextEffect: 'elastic', // 'elastic', 'fade' or 'none'
102
+ nextSpeed: 300,
103
+ nextEasing: 'swing',
104
+ nextMethod: 'changeIn',
105
+
106
+ // Changing previous gallery item
107
+ prevEffect: 'elastic', // 'elastic', 'fade' or 'none'
108
+ prevSpeed: 300,
109
+ prevEasing: 'swing',
110
+ prevMethod: 'changeOut',
111
+
112
+ // Enabled helpers
113
+ helpers: {
114
+ overlay: {
115
+ speedIn: 0,
116
+ speedOut: 300,
117
+ opacity: 0.8,
118
+ css: {
119
+ cursor: 'pointer'
120
+ },
121
+ closeClick: true
122
+ },
123
+ title: {
124
+ type: 'float' // 'float', 'inside', 'outside' or 'over'
125
+ }
126
+ },
127
+
128
+ // Callbacks
129
+ onCancel: $.noop, // If canceling
130
+ beforeLoad: $.noop, // Before loading
131
+ afterLoad: $.noop, // After loading
132
+ beforeShow: $.noop, // Before changing in current item
133
+ afterShow: $.noop, // After opening
134
+ beforeClose: $.noop, // Before closing
135
+ afterClose: $.noop // After closing
136
+ },
137
+
138
+ //Current state
139
+ group: {}, // Selected group
140
+ opts: {}, // Group options
141
+ coming: null, // Element being loaded
142
+ current: null, // Currently loaded element
143
+ isOpen: false, // Is currently open
144
+ isOpened: false, // Have been fully opened at least once
145
+ wrap: null,
146
+ outer: null,
147
+ inner: null,
148
+
149
+ player: {
150
+ timer: null,
151
+ isActive: false
152
+ },
153
+
154
+ // Loaders
155
+ ajaxLoad: null,
156
+ imgPreload: null,
157
+
158
+ // Some collections
159
+ transitions: {},
160
+ helpers: {},
161
+
162
+ /*
163
+ * Static methods
164
+ */
165
+
166
+ open: function (group, opts) {
167
+ //Kill existing instances
168
+ F.close(true);
169
+
170
+ //Normalize group
171
+ if (group && !$.isArray(group)) {
172
+ group = group instanceof $ ? $(group).get() : [group];
173
+ }
174
+
175
+ F.isActive = true;
176
+
177
+ //Extend the defaults
178
+ F.opts = $.extend(true, {}, F.defaults, opts);
179
+
180
+ //All options are merged recursive except keys
181
+ if ($.isPlainObject(opts) && typeof opts.keys !== 'undefined') {
182
+ F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false;
183
+ }
184
+
185
+ F.group = group;
186
+
187
+ F._start(F.opts.index || 0);
188
+ },
189
+
190
+ cancel: function () {
191
+ if (F.coming && false === F.trigger('onCancel')) {
192
+ return;
193
+ }
194
+
195
+ F.coming = null;
196
+
197
+ F.hideLoading();
198
+
199
+ if (F.ajaxLoad) {
200
+ F.ajaxLoad.abort();
201
+ }
202
+
203
+ F.ajaxLoad = null;
204
+
205
+ if (F.imgPreload) {
206
+ F.imgPreload.onload = F.imgPreload.onabort = F.imgPreload.onerror = null;
207
+ }
208
+ },
209
+
210
+ close: function (a) {
211
+ F.cancel();
212
+
213
+ if (!F.current || false === F.trigger('beforeClose')) {
214
+ return;
215
+ }
216
+
217
+ F.unbindEvents();
218
+
219
+ //If forced or is still opening then remove immediately
220
+ if (!F.isOpen || (a && a[0] === true)) {
221
+ $(".fancybox-wrap").stop().trigger('onReset').remove();
222
+
223
+ F._afterZoomOut();
224
+
225
+ } else {
226
+ F.isOpen = F.isOpened = false;
227
+
228
+ $(".fancybox-item, .fancybox-nav").remove();
229
+
230
+ F.wrap.stop(true).removeClass('fancybox-opened');
231
+ F.inner.css('overflow', 'hidden');
232
+
233
+ F.transitions[F.current.closeMethod]();
234
+ }
235
+ },
236
+
237
+ // Start/stop slideshow
238
+ play: function (a) {
239
+ var clear = function () {
240
+ clearTimeout(F.player.timer);
241
+ },
242
+ set = function () {
243
+ clear();
244
+
245
+ if (F.current && F.player.isActive) {
246
+ F.player.timer = setTimeout(F.next, F.current.playSpeed);
247
+ }
248
+ },
249
+ stop = function () {
250
+ clear();
251
+
252
+ $('body').unbind('.player');
253
+
254
+ F.player.isActive = false;
255
+
256
+ F.trigger('onPlayEnd');
257
+ },
258
+ start = function () {
259
+ if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {
260
+ F.player.isActive = true;
261
+
262
+ $('body').bind({
263
+ 'afterShow.player onUpdate.player': set,
264
+ 'onCancel.player beforeClose.player': stop,
265
+ 'beforeLoad.player': clear
266
+ });
267
+
268
+ set();
269
+
270
+ F.trigger('onPlayStart');
271
+ }
272
+ };
273
+
274
+ if (F.player.isActive || (a && a[0] === false)) {
275
+ stop();
276
+ } else {
277
+ start();
278
+ }
279
+ },
280
+
281
+ next: function () {
282
+ if (F.current) {
283
+ F.jumpto(F.current.index + 1);
284
+ }
285
+ },
286
+
287
+ prev: function () {
288
+ if (F.current) {
289
+ F.jumpto(F.current.index - 1);
290
+ }
291
+ },
292
+
293
+ jumpto: function (index) {
294
+ if (!F.current) {
295
+ return;
296
+ }
297
+
298
+ index = parseInt(index, 10);
299
+
300
+ if (F.group.length > 1 && F.current.loop) {
301
+ if (index >= F.group.length) {
302
+ index = 0;
303
+
304
+ } else if (index < 0) {
305
+ index = F.group.length - 1;
306
+ }
307
+ }
308
+
309
+ if (typeof F.group[index] !== 'undefined') {
310
+ F.cancel();
311
+
312
+ F._start(index);
313
+ }
314
+ },
315
+
316
+ reposition: function (a) {
317
+ if (F.isOpen) {
318
+ F.wrap.css(F._getPosition(a));
319
+ }
320
+ },
321
+
322
+ update: function (e) {
323
+ if (F.isOpen) {
324
+ // It's a very bad idea to attach handlers to the window scroll event, run this code after a delay
325
+ if (!didResize) {
326
+ resizeTimer = setTimeout(function () {
327
+ var current = F.current;
328
+
329
+ if (didResize) {
330
+ didResize = false;
331
+
332
+ if (current) {
333
+ if (current.autoResize || (e && e.type === 'orientationchange')) {
334
+ if (current.autoSize) {
335
+ F.inner.height('auto');
336
+ current.height = F.inner.height();
337
+ }
338
+
339
+ F._setDimension();
340
+
341
+ if (current.canGrow) {
342
+ F.inner.height('auto');
343
+ }
344
+ }
345
+
346
+ if (current.autoCenter) {
347
+ F.reposition();
348
+ }
349
+
350
+ F.trigger('onUpdate');
351
+ }
352
+ }
353
+ }, 100);
354
+ }
355
+
356
+ didResize = true;
357
+ }
358
+ },
359
+
360
+ toggle: function () {
361
+ if (F.isOpen) {
362
+ F.current.fitToView = !F.current.fitToView;
363
+
364
+ F.update();
365
+ }
366
+ },
367
+
368
+ hideLoading: function () {
369
+ $("#fancybox-loading").remove();
370
+ },
371
+
372
+ showLoading: function () {
373
+ F.hideLoading();
374
+
375
+ $('<div id="fancybox-loading"><div></div></div>').click(F.cancel).appendTo('body');
376
+ },
377
+
378
+ getViewport: function () {
379
+ return {
380
+ x: W.scrollLeft(),
381
+ y: W.scrollTop(),
382
+ w: W.width(),
383
+ h: W.height()
384
+ };
385
+ },
386
+
387
+ // Unbind the keyboard / clicking actions
388
+ unbindEvents: function () {
389
+ if (F.wrap) {
390
+ F.wrap.unbind('.fb');
391
+ }
392
+
393
+ D.unbind('.fb');
394
+ W.unbind('.fb');
395
+ },
396
+
397
+ bindEvents: function () {
398
+ var current = F.current,
399
+ keys = current.keys;
400
+
401
+ if (!current) {
402
+ return;
403
+ }
404
+
405
+ W.bind('resize.fb, orientationchange.fb', F.update);
406
+
407
+ if (keys) {
408
+ D.bind('keydown.fb', function (e) {
409
+ var code;
410
+
411
+ // Ignore key combinations and key events within form elements
412
+ if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && $.inArray(e.target.tagName.toLowerCase(), ['input', 'textarea', 'select', 'button']) < 0) {
413
+ code = e.keyCode;
414
+
415
+ if ($.inArray(code, keys.close) > -1) {
416
+ F.close();
417
+ e.preventDefault();
418
+
419
+ } else if ($.inArray(code, keys.next) > -1) {
420
+ F.next();
421
+ e.preventDefault();
422
+
423
+ } else if ($.inArray(code, keys.prev) > -1) {
424
+ F.prev();
425
+ e.preventDefault();
426
+ }
427
+ }
428
+ });
429
+ }
430
+
431
+ if ($.fn.mousewheel && current.mouseWheel && F.group.length > 1) {
432
+ F.wrap.bind('mousewheel.fb', function (e, delta) {
433
+ var target = $(e.target).get(0);
434
+
435
+ if (target.clientHeight === 0 || (target.scrollHeight === target.clientHeight && target.scrollWidth === target.clientWidth)) {
436
+ e.preventDefault();
437
+
438
+ F[delta > 0 ? 'prev' : 'next']();
439
+ }
440
+ });
441
+ }
442
+ },
443
+
444
+ trigger: function (event) {
445
+ var ret, obj = F[ $.inArray(event, ['onCancel', 'beforeLoad', 'afterLoad']) > -1 ? 'coming' : 'current' ];
446
+
447
+ if (!obj) {
448
+ return;
449
+ }
450
+
451
+ if ($.isFunction( obj[event] )) {
452
+ ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));
453
+ }
454
+
455
+ if (ret === false) {
456
+ return false;
457
+ }
458
+
459
+ if (obj.helpers) {
460
+ $.each(obj.helpers, function (helper, opts) {
461
+ if (opts && typeof F.helpers[helper] !== 'undefined' && $.isFunction(F.helpers[helper][event])) {
462
+ F.helpers[helper][event](opts, obj);
463
+ }
464
+ });
465
+ }
466
+
467
+ $.event.trigger(event + '.fb');
468
+ },
469
+
470
+ isImage: function (str) {
471
+ return str && str.match(/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i);
472
+ },
473
+
474
+ isSWF: function (str) {
475
+ return str && str.match(/\.(swf)(.*)?$/i);
476
+ },
477
+
478
+ _start: function (index) {
479
+ var coming = {},
480
+ element = F.group[index] || null,
481
+ isDom,
482
+ href,
483
+ type,
484
+ rez;
485
+
486
+ if (element && (element.nodeType || element instanceof $)) {
487
+ isDom = true;
488
+
489
+ if ($.metadata) {
490
+ coming = $(element).metadata();
491
+ }
492
+ }
493
+
494
+ coming = $.extend(true, {}, F.opts, {index : index, element : element}, ($.isPlainObject(element) ? element : coming));
495
+
496
+ // Re-check overridable options
497
+ $.each(['href', 'title', 'content', 'type'], function(i,v) {
498
+ coming[v] = F.opts[ v ] || (isDom && $(element).attr( v )) || coming[ v ] || null;
499
+ });
500
+
501
+ // Convert margin property to array - top, right, bottom, left
502
+ if (typeof coming.margin === 'number') {
503
+ coming.margin = [coming.margin, coming.margin, coming.margin, coming.margin];
504
+ }
505
+
506
+ // 'modal' propery is just a shortcut
507
+ if (coming.modal) {
508
+ $.extend(true, coming, {
509
+ closeBtn : false,
510
+ closeClick: false,
511
+ nextClick : false,
512
+ arrows : false,
513
+ mouseWheel : false,
514
+ keys : null,
515
+ helpers: {
516
+ overlay : {
517
+ css: {
518
+ cursor : 'auto'
519
+ },
520
+ closeClick : false
521
+ }
522
+ }
523
+ });
524
+ }
525
+
526
+ //Give a chance for callback or helpers to update coming item (type, title, etc)
527
+ F.coming = coming;
528
+
529
+ if (false === F.trigger('beforeLoad')) {
530
+ F.coming = null;
531
+ return;
532
+ }
533
+
534
+ type = coming.type;
535
+ href = coming.href || element;
536
+
537
+ ///Check if content type is set, if not, try to get
538
+ if (!type) {
539
+ if (isDom) {
540
+ rez = $(element).data('fancybox-type');
541
+
542
+ if (!rez && element.className) {
543
+ rez = element.className.match(/fancybox\.(\w+)/);
544
+ type = rez ? rez[1] : null;
545
+ }
546
+ }
547
+
548
+ if (!type && $.type(href) === "string") {
549
+ if (F.isImage(href)) {
550
+ type = 'image';
551
+
552
+ } else if (F.isSWF(href)) {
553
+ type = 'swf';
554
+
555
+ } else if (href.match(/^#/)) {
556
+ type = 'inline';
557
+ }
558
+ }
559
+
560
+ // ...if not - display element itself
561
+ if (!type) {
562
+ type = isDom ? 'inline' : 'html';
563
+ }
564
+
565
+ coming.type = type;
566
+ }
567
+
568
+ // Check before try to load; 'inline' and 'html' types need content, others - href
569
+ if (type === 'inline' || type === 'html') {
570
+ if (!coming.content) {
571
+ if (type === 'inline') {
572
+ coming.content = $( $.type(href) === "string" ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7
573
+
574
+ } else {
575
+ coming.content = element;
576
+ }
577
+ }
578
+
579
+ if (!coming.content || !coming.content.length) {
580
+ type = null;
581
+ }
582
+
583
+ } else if (!href) {
584
+ type = null;
585
+ }
586
+
587
+ /*
588
+ Add reference to the group, so it`s possible to access from callbacks, example:
589
+
590
+ afterLoad : function() {
591
+ this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');
592
+ }
593
+
594
+ */
595
+
596
+ coming.group = F.group;
597
+ coming.isDom = isDom;
598
+ coming.href = href;
599
+
600
+ if (type === 'image') {
601
+ F._loadImage();
602
+
603
+ } else if (type === 'ajax') {
604
+ F._loadAjax();
605
+
606
+ } else if (type) {
607
+ F._afterLoad();
608
+
609
+ } else {
610
+ F._error( 'type' );
611
+ }
612
+ },
613
+
614
+ _error: function ( type ) {
615
+ F.hideLoading();
616
+
617
+ $.extend(F.coming, {
618
+ type : 'html',
619
+ autoSize : true,
620
+ minHeight : 0,
621
+ hasError : type,
622
+ content : F.coming.tpl.error
623
+ });
624
+
625
+ F._afterLoad();
626
+ },
627
+
628
+ _loadImage: function () {
629
+ // Reset preload image so it is later possible to check "complete" property
630
+ F.imgPreload = new Image();
631
+
632
+ F.imgPreload.onload = function () {
633
+ this.onload = this.onerror = null;
634
+
635
+ F.coming.width = this.width;
636
+ F.coming.height = this.height;
637
+
638
+ F._afterLoad();
639
+ };
640
+
641
+ F.imgPreload.onerror = function () {
642
+ this.onload = this.onerror = null;
643
+
644
+ F._error( 'image' );
645
+ };
646
+
647
+ F.imgPreload.src = F.coming.href;
648
+
649
+ if (!F.imgPreload.width) {
650
+ F.showLoading();
651
+ }
652
+ },
653
+
654
+ _loadAjax: function () {
655
+ F.showLoading();
656
+
657
+ F.ajaxLoad = $.ajax($.extend({}, F.coming.ajax, {
658
+ url: F.coming.href,
659
+ error: function (jqXHR, textStatus) {
660
+ if (textStatus !== 'abort') {
661
+ F._error( 'ajax', jqXHR );
662
+
663
+ } else {
664
+ F.hideLoading();
665
+ }
666
+ },
667
+ success: function (data, textStatus) {
668
+ if (textStatus === 'success') {
669
+ F.coming.content = data;
670
+
671
+ F._afterLoad();
672
+ }
673
+ }
674
+ }));
675
+ },
676
+
677
+ _preloadImages: function() {
678
+ var group = F.group,
679
+ current = F.current,
680
+ len = group.length,
681
+ item,
682
+ href;
683
+
684
+ if (!current.preload || group.length < 2) {
685
+ return;
686
+ }
687
+
688
+ for (var i = 1; i <= Math.min(current.preload, len - 1); i++) {
689
+ item = group[ (current.index + i ) % len ];
690
+ href = $( item ).attr('href') || item;
691
+
692
+ if (href) {
693
+ new Image().src = href;
694
+ }
695
+ }
696
+ },
697
+
698
+ _afterLoad: function () {
699
+ F.hideLoading();
700
+
701
+ if (!F.coming || false === F.trigger('afterLoad', F.current)) {
702
+ F.coming = false;
703
+
704
+ return;
705
+ }
706
+
707
+ if (F.isOpened) {
708
+ $(".fancybox-item").remove();
709
+
710
+ F.wrap.stop(true).removeClass('fancybox-opened');
711
+ F.inner.css('overflow', 'hidden');
712
+
713
+ F.transitions[F.current.prevMethod]();
714
+
715
+ } else {
716
+ $(".fancybox-wrap").stop().trigger('onReset').remove();
717
+
718
+ F.trigger('afterClose');
719
+ }
720
+
721
+ F.unbindEvents();
722
+
723
+ F.isOpen = false;
724
+ F.current = F.coming;
725
+
726
+ //Build the neccessary markup
727
+ F.wrap = $(F.current.tpl.wrap).addClass('fancybox-' + (isMobile ? 'mobile' : 'desktop') + ' fancybox-tmp ' + F.current.wrapCSS).appendTo('body');
728
+ F.outer = $('.fancybox-outer', F.wrap).css('padding', F.current.padding + 'px');
729
+ F.inner = $('.fancybox-inner', F.wrap);
730
+
731
+ F._setContent();
732
+ },
733
+
734
+ _setContent: function () {
735
+ var content, loadingBay, iframe, current = F.current, type = current.type;
736
+
737
+ switch (type) {
738
+ case 'inline':
739
+ case 'ajax':
740
+ case 'html':
741
+ content = current.content;
742
+
743
+ if (content instanceof $) {
744
+ content = content.show().detach();
745
+
746
+ if (content.parent().hasClass('fancybox-inner')) {
747
+ content.parents('.fancybox-wrap').trigger('onReset').remove();
748
+ }
749
+
750
+ $(F.wrap).bind('onReset', function () {
751
+ content.appendTo('body').hide();
752
+ });
753
+ }
754
+
755
+ if (current.autoSize) {
756
+ loadingBay = $('<div class="fancybox-tmp ' + F.current.wrapCSS + '"></div>').appendTo('body').append(content);
757
+ current.width = loadingBay.width();
758
+ current.height = loadingBay.height();
759
+
760
+ // Re-check to fix 1px bug in some browsers
761
+ loadingBay.width( F.current.width );
762
+
763
+ if (loadingBay.height() > current.height) {
764
+ loadingBay.width(current.width + 1);
765
+
766
+ current.width = loadingBay.width();
767
+ current.height = loadingBay.height();
768
+ }
769
+
770
+ content = loadingBay.contents().detach();
771
+
772
+ loadingBay.remove();
773
+ }
774
+
775
+ break;
776
+
777
+ case 'image':
778
+ content = current.tpl.image.replace('{href}', current.href);
779
+
780
+ current.aspectRatio = true;
781
+ break;
782
+
783
+ case 'swf':
784
+ content = current.tpl.swf.replace(/\{width\}/g, current.width).replace(/\{height\}/g, current.height).replace(/\{href\}/g, current.href);
785
+ break;
786
+ }
787
+
788
+ if (type === 'iframe') {
789
+ content = $(current.tpl.iframe.replace('{rnd}', new Date().getTime()) ).attr('scrolling', current.scrolling);
790
+
791
+ current.scrolling = 'auto';
792
+
793
+ // Set auto height for iframes
794
+ if (current.autoSize) {
795
+ content.width( current.width );
796
+
797
+ F.showLoading();
798
+
799
+ content.data('ready', false).appendTo(F.inner).bind({
800
+ onCancel : function() {
801
+ $(this).unbind();
802
+
803
+ F._afterZoomOut();
804
+ },
805
+ load : function() {
806
+ var iframe = $(this), height;
807
+
808
+ try {
809
+ if (this.contentWindow.document.location) {
810
+ height = iframe.contents().find('body').height() + 12;
811
+
812
+ iframe.height( height );
813
+ }
814
+
815
+ } catch (e) {
816
+ current.autoSize = false;
817
+ }
818
+
819
+ if (iframe.data('ready') === false) {
820
+ F.hideLoading();
821
+
822
+ if (height) {
823
+ F.current.height = height;
824
+ }
825
+
826
+ F._beforeShow();
827
+
828
+ iframe.data('ready', true);
829
+
830
+ } else if (height) {
831
+ F.update();
832
+ }
833
+ }
834
+
835
+ }).attr('src', current.href);
836
+
837
+ return;
838
+
839
+ } else {
840
+ content.attr('src', current.href);
841
+ }
842
+
843
+ } else if (type === 'image' || type === 'swf') {
844
+ current.autoSize = false;
845
+ current.scrolling = 'visible';
846
+ }
847
+
848
+ F.inner.append(content);
849
+
850
+ F._beforeShow();
851
+ },
852
+
853
+ _beforeShow : function() {
854
+ F.coming = null;
855
+
856
+ //Give a chance for helpers or callbacks to update elements
857
+ F.trigger('beforeShow');
858
+
859
+ //Set initial dimensions and hide
860
+ F._setDimension();
861
+
862
+ F.wrap.hide().removeClass('fancybox-tmp');
863
+
864
+ F.bindEvents();
865
+ F._preloadImages();
866
+
867
+ F.transitions[ F.isOpened ? F.current.nextMethod : F.current.openMethod ]();
868
+ },
869
+
870
+ _setDimension: function () {
871
+ var wrap = F.wrap,
872
+ outer = F.outer,
873
+ inner = F.inner,
874
+ current = F.current,
875
+ viewport = F.getViewport(),
876
+ margin = current.margin,
877
+ padding2 = current.padding * 2,
878
+ width = current.width,
879
+ height = current.height,
880
+ maxWidth = current.maxWidth,
881
+ maxHeight = current.maxHeight,
882
+ minWidth = current.minWidth,
883
+ minHeight = current.minHeight,
884
+ ratio,
885
+ height_,
886
+ space;
887
+
888
+ viewport.w -= (margin[1] + margin[3]);
889
+ viewport.h -= (margin[0] + margin[2]);
890
+
891
+ if (width.toString().indexOf('%') > -1) {
892
+ width = (((viewport.w - padding2) * parseFloat(width)) / 100);
893
+ }
894
+
895
+ if (height.toString().indexOf('%') > -1) {
896
+ height = (((viewport.h - padding2) * parseFloat(height)) / 100);
897
+ }
898
+
899
+ ratio = width / height;
900
+
901
+ width += padding2;
902
+ height += padding2;
903
+
904
+ if (current.fitToView) {
905
+ maxWidth = Math.min(viewport.w, maxWidth);
906
+ maxHeight = Math.min(viewport.h, maxHeight);
907
+ }
908
+
909
+ if (current.aspectRatio) {
910
+ if (width > maxWidth) {
911
+ width = maxWidth;
912
+ height = ((width - padding2) / ratio) + padding2;
913
+ }
914
+
915
+ if (height > maxHeight) {
916
+ height = maxHeight;
917
+ width = ((height - padding2) * ratio) + padding2;
918
+ }
919
+
920
+ if (width < minWidth) {
921
+ width = minWidth;
922
+ height = ((width - padding2) / ratio) + padding2;
923
+ }
924
+
925
+ if (height < minHeight) {
926
+ height = minHeight;
927
+ width = ((height - padding2) * ratio) + padding2;
928
+ }
929
+
930
+ } else {
931
+ width = Math.max(minWidth, Math.min(width, maxWidth));
932
+ height = Math.max(minHeight, Math.min(height, maxHeight));
933
+ }
934
+
935
+ width = Math.round(width);
936
+ height = Math.round(height);
937
+
938
+ //Reset dimensions
939
+ $(wrap.add(outer).add(inner)).width('auto').height('auto');
940
+
941
+ inner.width(width - padding2).height(height - padding2);
942
+ wrap.width(width);
943
+
944
+ height_ = wrap.height(); // Real wrap height
945
+
946
+ //Fit wrapper inside
947
+ if (width > maxWidth || height_ > maxHeight) {
948
+ while ((width > maxWidth || height_ > maxHeight) && width > minWidth && height_ > minHeight) {
949
+ height = height - 10;
950
+
951
+ if (current.aspectRatio) {
952
+ width = Math.round(((height - padding2) * ratio) + padding2);
953
+
954
+ if (width < minWidth) {
955
+ width = minWidth;
956
+ height = ((width - padding2) / ratio) + padding2;
957
+ }
958
+
959
+ } else {
960
+ width = width - 10;
961
+ }
962
+
963
+ inner.width(width - padding2).height(height - padding2);
964
+ wrap.width(width);
965
+
966
+ height_ = wrap.height();
967
+ }
968
+ }
969
+
970
+ current.dim = {
971
+ width: width,
972
+ height: height_
973
+ };
974
+
975
+ current.canGrow = current.autoSize && height > minHeight && height < maxHeight;
976
+ current.canShrink = false;
977
+ current.canExpand = false;
978
+
979
+ if ((width - padding2) < current.width || (height - padding2) < current.height) {
980
+ current.canExpand = true;
981
+
982
+ } else if ((width > viewport.w || height_ > viewport.h) && width > minWidth && height > minHeight) {
983
+ current.canShrink = true;
984
+ }
985
+
986
+ space = height_ - padding2;
987
+
988
+ F.innerSpace = space - inner.height();
989
+ F.outerSpace = space - outer.height();
990
+ },
991
+
992
+ _getPosition: function (a) {
993
+ var current = F.current,
994
+ viewport = F.getViewport(),
995
+ margin = current.margin,
996
+ width = F.wrap.width() + margin[1] + margin[3],
997
+ height = F.wrap.height() + margin[0] + margin[2],
998
+ rez = {
999
+ position: 'absolute',
1000
+ top: margin[0] + viewport.y,
1001
+ left: margin[3] + viewport.x
1002
+ };
1003
+
1004
+ if (current.fixed && (!a || a[0] === false) && height <= viewport.h && width <= viewport.w) {
1005
+ rez = {
1006
+ position: 'fixed',
1007
+ top: margin[0],
1008
+ left: margin[3]
1009
+ };
1010
+ }
1011
+
1012
+ rez.top = Math.ceil(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio))) + 'px';
1013
+ rez.left = Math.ceil(Math.max(rez.left, rez.left + ((viewport.w - width) * 0.5))) + 'px';
1014
+
1015
+ return rez;
1016
+ },
1017
+
1018
+ _afterZoomIn: function () {
1019
+ var current = F.current, scrolling = current.scrolling;
1020
+
1021
+ F.isOpen = F.isOpened = true;
1022
+
1023
+ F.wrap.addClass('fancybox-opened').css('overflow', 'visible');
1024
+
1025
+ F.update();
1026
+
1027
+ F.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling));
1028
+
1029
+ //Assign a click event
1030
+ if (current.closeClick || current.nextClick) {
1031
+ F.inner.css('cursor', 'pointer').bind('click.fb', current.nextClick ? F.next : F.close);
1032
+ }
1033
+
1034
+ //Create a close button
1035
+ if (current.closeBtn) {
1036
+ $(current.tpl.closeBtn).appendTo(F.outer).bind('click.fb', F.close);
1037
+ }
1038
+
1039
+ //Create navigation arrows
1040
+ if (current.arrows && F.group.length > 1) {
1041
+ if (current.loop || current.index > 0) {
1042
+ $(current.tpl.prev).appendTo(F.inner).bind('click.fb', F.prev);
1043
+ }
1044
+
1045
+ if (current.loop || current.index < F.group.length - 1) {
1046
+ $(current.tpl.next).appendTo(F.inner).bind('click.fb', F.next);
1047
+ }
1048
+ }
1049
+
1050
+ F.trigger('afterShow');
1051
+
1052
+ if (F.opts.autoPlay && !F.player.isActive) {
1053
+ F.opts.autoPlay = false;
1054
+
1055
+ F.play();
1056
+ }
1057
+ },
1058
+
1059
+ _afterZoomOut: function () {
1060
+ F.trigger('afterClose');
1061
+
1062
+ F.wrap.trigger('onReset').remove();
1063
+
1064
+ $.extend(F, {
1065
+ group: {},
1066
+ opts: {},
1067
+ current: null,
1068
+ isActive: false,
1069
+ isOpened: false,
1070
+ isOpen: false,
1071
+ wrap: null,
1072
+ outer: null,
1073
+ inner: null
1074
+ });
1075
+ }
1076
+ });
1077
+
1078
+ /*
1079
+ * Default transitions
1080
+ */
1081
+
1082
+ F.transitions = {
1083
+ getOrigPosition: function () {
1084
+ var current = F.current,
1085
+ element = current.element,
1086
+ padding = current.padding,
1087
+ orig = $(current.orig),
1088
+ pos = {},
1089
+ width = 50,
1090
+ height = 50,
1091
+ viewport;
1092
+
1093
+ if (!orig.length && current.isDom && $(element).is(':visible')) {
1094
+ orig = $(element).find('img:first');
1095
+
1096
+ if (!orig.length) {
1097
+ orig = $(element);
1098
+ }
1099
+ }
1100
+
1101
+ if (orig.length) {
1102
+ pos = orig.offset();
1103
+
1104
+ if (orig.is('img')) {
1105
+ width = orig.outerWidth();
1106
+ height = orig.outerHeight();
1107
+ }
1108
+
1109
+ } else {
1110
+ viewport = F.getViewport();
1111
+
1112
+ pos.top = viewport.y + (viewport.h - height) * 0.5;
1113
+ pos.left = viewport.x + (viewport.w - width) * 0.5;
1114
+ }
1115
+
1116
+ pos = {
1117
+ top: Math.ceil(pos.top - padding) + 'px',
1118
+ left: Math.ceil(pos.left - padding) + 'px',
1119
+ width: Math.ceil(width + padding * 2) + 'px',
1120
+ height: Math.ceil(height + padding * 2) + 'px'
1121
+ };
1122
+
1123
+ return pos;
1124
+ },
1125
+
1126
+ step: function (now, fx) {
1127
+ var ratio, innerValue, outerValue;
1128
+
1129
+ if (fx.prop === 'width' || fx.prop === 'height') {
1130
+ innerValue = outerValue = Math.ceil(now - (F.current.padding * 2));
1131
+
1132
+ if (fx.prop === 'height') {
1133
+ ratio = (now - fx.start) / (fx.end - fx.start);
1134
+
1135
+ if (fx.start > fx.end) {
1136
+ ratio = 1 - ratio;
1137
+ }
1138
+
1139
+ innerValue -= F.innerSpace * ratio;
1140
+ outerValue -= F.outerSpace * ratio;
1141
+ }
1142
+
1143
+ F.inner[fx.prop](innerValue);
1144
+ F.outer[fx.prop](outerValue);
1145
+ }
1146
+ },
1147
+
1148
+ zoomIn: function () {
1149
+ var wrap = F.wrap,
1150
+ current = F.current,
1151
+ startPos,
1152
+ endPos,
1153
+ dim = current.dim;
1154
+
1155
+ if (current.openEffect === 'elastic') {
1156
+ endPos = $.extend({}, dim, F._getPosition(true));
1157
+
1158
+ //Remove "position" property
1159
+ delete endPos.position;
1160
+
1161
+ startPos = this.getOrigPosition();
1162
+
1163
+ if (current.openOpacity) {
1164
+ startPos.opacity = 0;
1165
+ endPos.opacity = 1;
1166
+ }
1167
+
1168
+ F.outer.add(F.inner).width('auto').height('auto');
1169
+
1170
+ wrap.css(startPos).show();
1171
+
1172
+ wrap.animate(endPos, {
1173
+ duration: current.openSpeed,
1174
+ easing: current.openEasing,
1175
+ step: this.step,
1176
+ complete: F._afterZoomIn
1177
+ });
1178
+
1179
+ } else {
1180
+ wrap.css($.extend({}, dim, F._getPosition()));
1181
+
1182
+ if (current.openEffect === 'fade') {
1183
+ wrap.fadeIn(current.openSpeed, F._afterZoomIn);
1184
+
1185
+ } else {
1186
+ wrap.show();
1187
+ F._afterZoomIn();
1188
+ }
1189
+ }
1190
+ },
1191
+
1192
+ zoomOut: function () {
1193
+ var wrap = F.wrap,
1194
+ current = F.current,
1195
+ endPos;
1196
+
1197
+ if (current.closeEffect === 'elastic') {
1198
+ if (wrap.css('position') === 'fixed') {
1199
+ wrap.css(F._getPosition(true));
1200
+ }
1201
+
1202
+ endPos = this.getOrigPosition();
1203
+
1204
+ if (current.closeOpacity) {
1205
+ endPos.opacity = 0;
1206
+ }
1207
+
1208
+ wrap.animate(endPos, {
1209
+ duration: current.closeSpeed,
1210
+ easing: current.closeEasing,
1211
+ step: this.step,
1212
+ complete: F._afterZoomOut
1213
+ });
1214
+
1215
+ } else {
1216
+ wrap.fadeOut(current.closeEffect === 'fade' ? current.closeSpeed : 0, F._afterZoomOut);
1217
+ }
1218
+ },
1219
+
1220
+ changeIn: function () {
1221
+ var wrap = F.wrap,
1222
+ current = F.current,
1223
+ startPos;
1224
+
1225
+ if (current.nextEffect === 'elastic') {
1226
+ startPos = F._getPosition(true);
1227
+ startPos.opacity = 0;
1228
+ startPos.top = (parseInt(startPos.top, 10) - 200) + 'px';
1229
+
1230
+ wrap.css(startPos).show().animate({
1231
+ opacity: 1,
1232
+ top: '+=200px'
1233
+ }, {
1234
+ duration: current.nextSpeed,
1235
+ easing: current.nextEasing,
1236
+ complete: F._afterZoomIn
1237
+ });
1238
+
1239
+ } else {
1240
+ wrap.css(F._getPosition());
1241
+
1242
+ if (current.nextEffect === 'fade') {
1243
+ wrap.hide().fadeIn(current.nextSpeed, F._afterZoomIn);
1244
+
1245
+ } else {
1246
+ wrap.show();
1247
+ F._afterZoomIn();
1248
+ }
1249
+ }
1250
+ },
1251
+
1252
+ changeOut: function () {
1253
+ var wrap = F.wrap,
1254
+ current = F.current,
1255
+ cleanUp = function () {
1256
+ $(this).trigger('onReset').remove();
1257
+ };
1258
+
1259
+ wrap.removeClass('fancybox-opened');
1260
+
1261
+ if (current.prevEffect === 'elastic') {
1262
+ wrap.animate({
1263
+ 'opacity': 0,
1264
+ top: '+=200px'
1265
+ }, {
1266
+ duration: current.prevSpeed,
1267
+ easing: current.prevEasing,
1268
+ complete: cleanUp
1269
+ });
1270
+
1271
+ } else {
1272
+ wrap.fadeOut(current.prevEffect === 'fade' ? current.prevSpeed : 0, cleanUp);
1273
+ }
1274
+ }
1275
+ };
1276
+
1277
+ /*
1278
+ * Overlay helper
1279
+ */
1280
+
1281
+ F.helpers.overlay = {
1282
+ overlay: null,
1283
+
1284
+ update: function () {
1285
+ var width, scrollWidth, offsetWidth;
1286
+
1287
+ //Reset width/height so it will not mess
1288
+ this.overlay.width(0).height(0);
1289
+
1290
+ if ($.browser.msie) {
1291
+ scrollWidth = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);
1292
+ offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);
1293
+
1294
+ width = scrollWidth < offsetWidth ? W.width() : scrollWidth;
1295
+
1296
+ } else {
1297
+ width = D.width();
1298
+ }
1299
+
1300
+ this.overlay.width(width).height(D.height());
1301
+ },
1302
+
1303
+ beforeShow: function (opts) {
1304
+ if (this.overlay) {
1305
+ return;
1306
+ }
1307
+
1308
+ opts = $.extend(true, {
1309
+ speedIn : 'fast',
1310
+ closeClick : true,
1311
+ opacity : 1,
1312
+ css : {
1313
+ background: 'black'
1314
+ }
1315
+ }, opts);
1316
+
1317
+ this.overlay = $('<div id="fancybox-overlay"></div>').css(opts.css).appendTo('body');
1318
+
1319
+ this.update();
1320
+
1321
+ if (opts.closeClick) {
1322
+ this.overlay.bind('click.fb', F.close);
1323
+ }
1324
+
1325
+ W.bind("resize.fb", $.proxy(this.update, this));
1326
+
1327
+ this.overlay.fadeTo(opts.speedIn, opts.opacity);
1328
+ },
1329
+
1330
+ onUpdate: function () {
1331
+ //Update as content may change document dimensions
1332
+ this.update();
1333
+ },
1334
+
1335
+ afterClose: function (opts) {
1336
+ if (this.overlay) {
1337
+
1338
+ this.overlay.fadeOut(opts.speedOut || 0, function () {
1339
+ $(this).remove();
1340
+ });
1341
+ }
1342
+
1343
+ this.overlay = null;
1344
+ }
1345
+ };
1346
+
1347
+ /*
1348
+ * Title helper
1349
+ */
1350
+
1351
+ F.helpers.title = {
1352
+ beforeShow: function (opts) {
1353
+ var title, text = F.current.title;
1354
+
1355
+ if (text) {
1356
+ title = $('<div class="fancybox-title fancybox-title-' + opts.type + '-wrap">' + text + '</div>').appendTo('body');
1357
+
1358
+ if (opts.type === 'float') {
1359
+ //This helps for some browsers
1360
+ title.width(title.width());
1361
+
1362
+ title.wrapInner('<span class="child"></span>');
1363
+
1364
+ //Increase bottom margin so this title will also fit into viewport
1365
+ F.current.margin[2] += Math.abs(parseInt(title.css('margin-bottom'), 10));
1366
+ }
1367
+
1368
+ title.appendTo(opts.type === 'over' ? F.inner : (opts.type === 'outside' ? F.wrap : F.outer));
1369
+ }
1370
+ }
1371
+ };
1372
+
1373
+ // jQuery plugin initialization
1374
+ $.fn.fancybox = function (options) {
1375
+ var that = $(this),
1376
+ selector = this.selector || '',
1377
+ index,
1378
+ run = function(e) {
1379
+ var what = this, relType = 'rel', relVal = what[ relType ], idx = index;
1380
+
1381
+ if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) {
1382
+ e.preventDefault();
1383
+
1384
+ if (!relVal) {
1385
+ relType = 'data-fancybox-group';
1386
+ relVal = $(what).attr('data-fancybox-group');
1387
+ }
1388
+
1389
+ if (relVal && relVal !== '' && relVal !== 'nofollow') {
1390
+ what = selector.length ? $(selector) : that;
1391
+ what = what.filter('[' + relType + '="' + relVal + '"]');
1392
+ idx = what.index(this);
1393
+ }
1394
+
1395
+ options.index = idx;
1396
+
1397
+ F.open(what, options);
1398
+ }
1399
+ };
1400
+
1401
+ options = options || {};
1402
+ index = options.index || 0;
1403
+
1404
+ if (selector) {
1405
+ D.undelegate(selector, 'click.fb-start').delegate(selector, 'click.fb-start', run);
1406
+
1407
+ } else {
1408
+ that.unbind('click.fb-start').bind('click.fb-start', run);
1409
+ }
1410
+
1411
+ return this;
1412
+ };
1413
+
1414
+ }(window, document, jQuery));