Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / new_ui / ui / javascripts / jquery.magnific-popup.js @ 1eb800de

History | View | Annotate | Download (44.2 kB)

1
/*! Magnific Popup - v0.9.5 - 2013-08-21
2
* http://dimsemenov.com/plugins/magnific-popup/
3
* Copyright (c) 2013 Dmitry Semenov; */
4
;(function($) {
5

    
6
/*>>core*/
7
/**
8
 * 
9
 * Magnific Popup Core JS file
10
 * 
11
 */
12

    
13

    
14
/**
15
 * Private static constants
16
 */
17
var CLOSE_EVENT = 'Close',
18
        BEFORE_CLOSE_EVENT = 'BeforeClose',
19
        AFTER_CLOSE_EVENT = 'AfterClose',
20
        BEFORE_APPEND_EVENT = 'BeforeAppend',
21
        MARKUP_PARSE_EVENT = 'MarkupParse',
22
        OPEN_EVENT = 'Open',
23
        CHANGE_EVENT = 'Change',
24
        NS = 'mfp',
25
        EVENT_NS = '.' + NS,
26
        READY_CLASS = 'mfp-ready',
27
        REMOVING_CLASS = 'mfp-removing',
28
        PREVENT_CLOSE_CLASS = 'mfp-prevent-close';
29

    
30

    
31
/**
32
 * Private vars 
33
 */
34
var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this'
35
        MagnificPopup = function(){},
36
        _isJQ = !!(window.jQuery),
37
        _prevStatus,
38
        _window = $(window),
39
        _body,
40
        _document,
41
        _prevContentType,
42
        _wrapClasses,
43
        _currPopupType;
44

    
45

    
46
/**
47
 * Private functions
48
 */
49
var _mfpOn = function(name, f) {
50
                mfp.ev.on(NS + name + EVENT_NS, f);
51
        },
52
        _getEl = function(className, appendTo, html, raw) {
53
                var el = document.createElement('div');
54
                el.className = 'mfp-'+className;
55
                if(html) {
56
                        el.innerHTML = html;
57
                }
58
                if(!raw) {
59
                        el = $(el);
60
                        if(appendTo) {
61
                                el.appendTo(appendTo);
62
                        }
63
                } else if(appendTo) {
64
                        appendTo.appendChild(el);
65
                }
66
                return el;
67
        },
68
        _mfpTrigger = function(e, data) {
69
                mfp.ev.triggerHandler(NS + e, data);
70

    
71
                if(mfp.st.callbacks) {
72
                        // converts "mfpEventName" to "eventName" callback and triggers it if it's present
73
                        e = e.charAt(0).toLowerCase() + e.slice(1);
74
                        if(mfp.st.callbacks[e]) {
75
                                mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
76
                        }
77
                }
78
        },
79
        _setFocus = function() {
80
                (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
81
        },
82
        _getCloseBtn = function(type) {
83
                if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
84
                        mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
85
                        _currPopupType = type;
86
                }
87
                return mfp.currTemplate.closeBtn;
88
        },
89
        // Initialize Magnific Popup only when called at least once
90
        _checkInstance = function() {
91
                if(!$.magnificPopup.instance) {
92
                        mfp = new MagnificPopup();
93
                        mfp.init();
94
                        $.magnificPopup.instance = mfp;
95
                }
96
        },
97
        // Check to close popup or not
98
        // "target" is an element that was clicked
99
        _checkIfClose = function(target) {
100

    
101
                if($(target).hasClass(PREVENT_CLOSE_CLASS)) {
102
                        return;
103
                }
104

    
105
                var closeOnContent = mfp.st.closeOnContentClick;
106
                var closeOnBg = mfp.st.closeOnBgClick;
107

    
108
                if(closeOnContent && closeOnBg) {
109
                        return true;
110
                } else {
111

    
112
                        // We close the popup if click is on close button or on preloader. Or if there is no content.
113
                        if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) {
114
                                return true;
115
                        }
116

    
117
                        // if click is outside the content
118
                        if(  (target !== mfp.content[0] && !$.contains(mfp.content[0], target))  ) {
119
                                if(closeOnBg) {
120
                                        // last check, if the clicked element is in DOM, (in case it's removed onclick)
121
                                        if( $.contains(document, target) ) {
122
                                                return true;
123
                                        }
124
                                }
125
                        } else if(closeOnContent) {
126
                                return true;
127
                        }
128

    
129
                }
130
                return false;
131
        },
132
        // CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
133
        supportsTransitions = function() {
134
                var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
135
                        v = ['ms','O','Moz','Webkit']; // 'v' for vendor
136

    
137
                if( s['transition'] !== undefined ) {
138
                        return true; 
139
                }
140
                        
141
                while( v.length ) {
142
                        if( v.pop() + 'Transition' in s ) {
143
                                return true;
144
                        }
145
                }
146
                                
147
                return false;
148
        };
149

    
150

    
151

    
152
/**
153
 * Public functions
154
 */
155
MagnificPopup.prototype = {
156

    
157
        constructor: MagnificPopup,
158

    
159
        /**
160
         * Initializes Magnific Popup plugin. 
161
         * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
162
         */
163
        init: function() {
164
                var appVersion = navigator.appVersion;
165
                mfp.isIE7 = appVersion.indexOf("MSIE 7.") !== -1; 
166
                mfp.isIE8 = appVersion.indexOf("MSIE 8.") !== -1;
167
                mfp.isLowIE = mfp.isIE7 || mfp.isIE8;
168
                mfp.isAndroid = (/android/gi).test(appVersion);
169
                mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
170
                mfp.supportsTransition = supportsTransitions();
171

    
172
                // We disable fixed positioned lightbox on devices that don't handle it nicely.
173
                // If you know a better way of detecting this - let me know.
174
                mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
175
                _body = $(document.body);
176
                _document = $(document);
177

    
178
                mfp.popupsCache = {};
179
        },
180

    
181
        /**
182
         * Opens popup
183
         * @param  data [description]
184
         */
185
        open: function(data) {
186

    
187
                var i;
188

    
189
                if(data.isObj === false) { 
190
                        // convert jQuery collection to array to avoid conflicts later
191
                        mfp.items = data.items.toArray();
192

    
193
                        mfp.index = 0;
194
                        var items = data.items,
195
                                item;
196
                        for(i = 0; i < items.length; i++) {
197
                                item = items[i];
198
                                if(item.parsed) {
199
                                        item = item.el[0];
200
                                }
201
                                if(item === data.el[0]) {
202
                                        mfp.index = i;
203
                                        break;
204
                                }
205
                        }
206
                } else {
207
                        mfp.items = $.isArray(data.items) ? data.items : [data.items];
208
                        mfp.index = data.index || 0;
209
                }
210

    
211
                // if popup is already opened - we just update the content
212
                if(mfp.isOpen) {
213
                        mfp.updateItemHTML();
214
                        return;
215
                }
216
                
217
                mfp.types = []; 
218
                _wrapClasses = '';
219
                if(data.mainEl && data.mainEl.length) {
220
                        mfp.ev = data.mainEl.eq(0);
221
                } else {
222
                        mfp.ev = _document;
223
                }
224

    
225
                if(data.key) {
226
                        if(!mfp.popupsCache[data.key]) {
227
                                mfp.popupsCache[data.key] = {};
228
                        }
229
                        mfp.currTemplate = mfp.popupsCache[data.key];
230
                } else {
231
                        mfp.currTemplate = {};
232
                }
233

    
234

    
235

    
236
                mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); 
237
                mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;
238

    
239
                if(mfp.st.modal) {
240
                        mfp.st.closeOnContentClick = false;
241
                        mfp.st.closeOnBgClick = false;
242
                        mfp.st.showCloseBtn = false;
243
                        mfp.st.enableEscapeKey = false;
244
                }
245
                
246

    
247
                // Building markup
248
                // main containers are created only once
249
                if(!mfp.bgOverlay) {
250

    
251
                        // Dark overlay
252
                        mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() {
253
                                mfp.close();
254
                        });
255

    
256
                        mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) {
257
                                if(_checkIfClose(e.target)) {
258
                                        mfp.close();
259
                                }
260
                        });
261

    
262
                        mfp.container = _getEl('container', mfp.wrap);
263
                }
264

    
265
                mfp.contentContainer = _getEl('content');
266
                if(mfp.st.preloader) {
267
                        mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading);
268
                }
269

    
270

    
271
                // Initializing modules
272
                var modules = $.magnificPopup.modules;
273
                for(i = 0; i < modules.length; i++) {
274
                        var n = modules[i];
275
                        n = n.charAt(0).toUpperCase() + n.slice(1);
276
                        mfp['init'+n].call(mfp);
277
                }
278
                _mfpTrigger('BeforeOpen');
279

    
280

    
281
                if(mfp.st.showCloseBtn) {
282
                        // Close button
283
                        if(!mfp.st.closeBtnInside) {
284
                                mfp.wrap.append( _getCloseBtn() );
285
                        } else {
286
                                _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
287
                                        values.close_replaceWith = _getCloseBtn(item.type);
288
                                });
289
                                _wrapClasses += ' mfp-close-btn-in';
290
                        }
291
                }
292

    
293
                if(mfp.st.alignTop) {
294
                        _wrapClasses += ' mfp-align-top';
295
                }
296

    
297
        
298

    
299
                if(mfp.fixedContentPos) {
300
                        mfp.wrap.css({
301
                                overflow: mfp.st.overflowY,
302
                                overflowX: 'hidden',
303
                                overflowY: mfp.st.overflowY
304
                        });
305
                } else {
306
                        mfp.wrap.css({ 
307
                                top: _window.scrollTop(),
308
                                position: 'absolute'
309
                        });
310
                }
311
                if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) {
312
                        mfp.bgOverlay.css({
313
                                height: _document.height(),
314
                                position: 'absolute'
315
                        });
316
                }
317

    
318
                
319

    
320
                if(mfp.st.enableEscapeKey) {
321
                        // Close on ESC key
322
                        _document.on('keyup' + EVENT_NS, function(e) {
323
                                if(e.keyCode === 27) {
324
                                        mfp.close();
325
                                }
326
                        });
327
                }
328

    
329
                _window.on('resize' + EVENT_NS, function() {
330
                        mfp.updateSize();
331
                });
332

    
333

    
334
                if(!mfp.st.closeOnContentClick) {
335
                        _wrapClasses += ' mfp-auto-cursor';
336
                }
337
                
338
                if(_wrapClasses)
339
                        mfp.wrap.addClass(_wrapClasses);
340

    
341

    
342
                // this triggers recalculation of layout, so we get it once to not to trigger twice
343
                var windowHeight = mfp.wH = _window.height();
344

    
345
                
346
                var windowStyles = {};
347

    
348
                if( mfp.fixedContentPos ) {
349
            if(mfp._hasScrollBar(windowHeight)){
350
                var s = mfp._getScrollbarSize();
351
                if(s) {
352
                    windowStyles.paddingRight = s;
353
                }
354
            }
355
        }
356

    
357
                if(mfp.fixedContentPos) {
358
                        if(!mfp.isIE7) {
359
                                windowStyles.overflow = 'hidden';
360
                        } else {
361
                                // ie7 double-scroll bug
362
                                $('body, html').css('overflow', 'hidden');
363
                        }
364
                }
365

    
366
                
367
                
368
                var classesToadd = mfp.st.mainClass;
369
                if(mfp.isIE7) {
370
                        classesToadd += ' mfp-ie7';
371
                }
372
                if(classesToadd) {
373
                        mfp._addClassToMFP( classesToadd );
374
                }
375

    
376
                // add content
377
                mfp.updateItemHTML();
378

    
379
                _mfpTrigger('BuildControls');
380

    
381

    
382
                // remove scrollbar, add padding e.t.c
383
                $('html').css(windowStyles);
384
                
385
                // add everything to DOM
386
                mfp.bgOverlay.add(mfp.wrap).prependTo( document.body );
387

    
388

    
389

    
390
                // Save last focused element
391
                mfp._lastFocusedEl = document.activeElement;
392
                
393
                // Wait for next cycle to allow CSS transition
394
                setTimeout(function() {
395
                        
396
                        if(mfp.content) {
397
                                mfp._addClassToMFP(READY_CLASS);
398
                                _setFocus();
399
                        } else {
400
                                // if content is not defined (not loaded e.t.c) we add class only for BG
401
                                mfp.bgOverlay.addClass(READY_CLASS);
402
                        }
403
                        
404
                        // Trap the focus in popup
405
                        _document.on('focusin' + EVENT_NS, function (e) {
406
                                if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) {
407
                                        _setFocus();
408
                                        return false;
409
                                }
410
                        });
411

    
412
                }, 16);
413

    
414
                mfp.isOpen = true;
415
                mfp.updateSize(windowHeight);
416
                _mfpTrigger(OPEN_EVENT);
417
        },
418

    
419
        /**
420
         * Closes the popup
421
         */
422
        close: function() {
423
                if(!mfp.isOpen) return;
424
                _mfpTrigger(BEFORE_CLOSE_EVENT);
425

    
426
                mfp.isOpen = false;
427
                // for CSS3 animation
428
                if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition )  {
429
                        mfp._addClassToMFP(REMOVING_CLASS);
430
                        setTimeout(function() {
431
                                mfp._close();
432
                        }, mfp.st.removalDelay);
433
                } else {
434
                        mfp._close();
435
                }
436
        },
437

    
438
        /**
439
         * Helper for close() function
440
         */
441
        _close: function() {
442
                _mfpTrigger(CLOSE_EVENT);
443

    
444
                var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' ';
445

    
446
                mfp.bgOverlay.detach();
447
                mfp.wrap.detach();
448
                mfp.container.empty();
449

    
450
                if(mfp.st.mainClass) {
451
                        classesToRemove += mfp.st.mainClass + ' ';
452
                }
453

    
454
                mfp._removeClassFromMFP(classesToRemove);
455

    
456
                if(mfp.fixedContentPos) {
457
                        var windowStyles = {paddingRight: ''};
458
                        if(mfp.isIE7) {
459
                                $('body, html').css('overflow', '');
460
                        } else {
461
                                windowStyles.overflow = '';
462
                        }
463
                        $('html').css(windowStyles);
464
                }
465
                
466
                _document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS);
467
                mfp.ev.off(EVENT_NS);
468

    
469
                // clean up DOM elements that aren't removed
470
                mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style');
471
                mfp.bgOverlay.attr('class', 'mfp-bg');
472
                mfp.container.attr('class', 'mfp-container');
473

    
474
                // remove close button from target element
475
                if(mfp.st.showCloseBtn &&
476
                (!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) {
477
                        if(mfp.currTemplate.closeBtn)
478
                                mfp.currTemplate.closeBtn.detach();
479
                }
480

    
481

    
482
                if(mfp._lastFocusedEl) {
483
                        $(mfp._lastFocusedEl).focus(); // put tab focus back
484
                }
485
                mfp.currItem = null;        
486
                mfp.content = null;
487
                mfp.currTemplate = null;
488
                mfp.prevHeight = 0;
489

    
490
                _mfpTrigger(AFTER_CLOSE_EVENT);
491
        },
492
        
493
        updateSize: function(winHeight) {
494

    
495
                if(mfp.isIOS) {
496
                        // fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2
497
                        var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
498
                        var height = window.innerHeight * zoomLevel;
499
                        mfp.wrap.css('height', height);
500
                        mfp.wH = height;
501
                } else {
502
                        mfp.wH = winHeight || _window.height();
503
                }
504
                // Fixes #84: popup incorrectly positioned with position:relative on body
505
                if(!mfp.fixedContentPos) {
506
                        mfp.wrap.css('height', mfp.wH);
507
                }
508

    
509
                _mfpTrigger('Resize');
510

    
511
        },
512

    
513
        /**
514
         * Set content of popup based on current index
515
         */
516
        updateItemHTML: function() {
517
                var item = mfp.items[mfp.index];
518

    
519
                // Detach and perform modifications
520
                mfp.contentContainer.detach();
521

    
522
                if(mfp.content)
523
                        mfp.content.detach();
524

    
525
                if(!item.parsed) {
526
                        item = mfp.parseEl( mfp.index );
527
                }
528

    
529
                var type = item.type;        
530

    
531
                _mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]);
532
                // BeforeChange event works like so:
533
                // _mfpOn('BeforeChange', function(e, prevType, newType) { });
534
                
535
                mfp.currItem = item;
536

    
537
                
538

    
539
                
540

    
541
                if(!mfp.currTemplate[type]) {
542
                        var markup = mfp.st[type] ? mfp.st[type].markup : false;
543

    
544
                        // allows to modify markup
545
                        _mfpTrigger('FirstMarkupParse', markup);
546

    
547
                        if(markup) {
548
                                mfp.currTemplate[type] = $(markup);
549
                        } else {
550
                                // if there is no markup found we just define that template is parsed
551
                                mfp.currTemplate[type] = true;
552
                        }
553
                }
554

    
555
                if(_prevContentType && _prevContentType !== item.type) {
556
                        mfp.container.removeClass('mfp-'+_prevContentType+'-holder');
557
                }
558
                
559
                var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]);
560
                mfp.appendContent(newContent, type);
561

    
562
                item.preloaded = true;
563

    
564
                _mfpTrigger(CHANGE_EVENT, item);
565
                _prevContentType = item.type;
566
                
567
                // Append container back after its content changed
568
                mfp.container.prepend(mfp.contentContainer);
569

    
570
                _mfpTrigger('AfterChange');
571
        },
572

    
573

    
574
        /**
575
         * Set HTML content of popup
576
         */
577
        appendContent: function(newContent, type) {
578
                mfp.content = newContent;
579
                
580
                if(newContent) {
581
                        if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
582
                                mfp.currTemplate[type] === true) {
583
                                // if there is no markup, we just append close button element inside
584
                                if(!mfp.content.find('.mfp-close').length) {
585
                                        mfp.content.append(_getCloseBtn());
586
                                }
587
                        } else {
588
                                mfp.content = newContent;
589
                        }
590
                } else {
591
                        mfp.content = '';
592
                }
593

    
594
                _mfpTrigger(BEFORE_APPEND_EVENT);
595
                mfp.container.addClass('mfp-'+type+'-holder');
596

    
597
                mfp.contentContainer.append(mfp.content);
598
        },
599

    
600

    
601

    
602
        
603
        /**
604
         * Creates Magnific Popup data object based on given data
605
         * @param  {int} index Index of item to parse
606
         */
607
        parseEl: function(index) {
608
                var item = mfp.items[index],
609
                        type = item.type;
610

    
611
                if(item.tagName) {
612
                        item = { el: $(item) };
613
                } else {
614
                        item = { data: item, src: item.src };
615
                }
616

    
617
                if(item.el) {
618
                        var types = mfp.types;
619

    
620
                        // check for 'mfp-TYPE' class
621
                        for(var i = 0; i < types.length; i++) {
622
                                if( item.el.hasClass('mfp-'+types[i]) ) {
623
                                        type = types[i];
624
                                        break;
625
                                }
626
                        }
627

    
628
                        item.src = item.el.attr('data-mfp-src');
629
                        if(!item.src) {
630
                                item.src = item.el.attr('href');
631
                        }
632
                }
633

    
634
                item.type = type || mfp.st.type || 'inline';
635
                item.index = index;
636
                item.parsed = true;
637
                mfp.items[index] = item;
638
                _mfpTrigger('ElementParse', item);
639

    
640
                return mfp.items[index];
641
        },
642

    
643

    
644
        /**
645
         * Initializes single popup or a group of popups
646
         */
647
        addGroup: function(el, options) {
648
                var eHandler = function(e) {
649
                        e.mfpEl = this;
650
                        mfp._openClick(e, el, options);
651
                };
652

    
653
                if(!options) {
654
                        options = {};
655
                } 
656

    
657
                var eName = 'click.magnificPopup';
658
                options.mainEl = el;
659
                
660
                if(options.items) {
661
                        options.isObj = true;
662
                        el.off(eName).on(eName, eHandler);
663
                } else {
664
                        options.isObj = false;
665
                        if(options.delegate) {
666
                                el.off(eName).on(eName, options.delegate , eHandler);
667
                        } else {
668
                                options.items = el;
669
                                el.off(eName).on(eName, eHandler);
670
                        }
671
                }
672
        },
673
        _openClick: function(e, el, options) {
674
                var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick;
675

    
676

    
677
                if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey ) ) {
678
                        return;
679
                }
680

    
681
                var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;
682

    
683
                if(disableOn) {
684
                        if($.isFunction(disableOn)) {
685
                                if( !disableOn.call(mfp) ) {
686
                                        return true;
687
                                }
688
                        } else { // else it's number
689
                                if( _window.width() < disableOn ) {
690
                                        return true;
691
                                }
692
                        }
693
                }
694
                
695
                if(e.type) {
696
                        e.preventDefault();
697

    
698
                        // This will prevent popup from closing if element is inside and popup is already opened
699
                        if(mfp.isOpen) {
700
                                e.stopPropagation();
701
                        }
702
                }
703
                        
704

    
705
                options.el = $(e.mfpEl);
706
                if(options.delegate) {
707
                        options.items = el.find(options.delegate);
708
                }
709
                mfp.open(options);
710
        },
711

    
712

    
713
        /**
714
         * Updates text on preloader
715
         */
716
        updateStatus: function(status, text) {
717

    
718
                if(mfp.preloader) {
719
                        if(_prevStatus !== status) {
720
                                mfp.container.removeClass('mfp-s-'+_prevStatus);
721
                        }
722

    
723
                        if(!text && status === 'loading') {
724
                                text = mfp.st.tLoading;
725
                        }
726

    
727
                        var data = {
728
                                status: status,
729
                                text: text
730
                        };
731
                        // allows to modify status
732
                        _mfpTrigger('UpdateStatus', data);
733

    
734
                        status = data.status;
735
                        text = data.text;
736

    
737
                        mfp.preloader.html(text);
738

    
739
                        mfp.preloader.find('a').on('click', function(e) {
740
                                e.stopImmediatePropagation();
741
                        });
742

    
743
                        mfp.container.addClass('mfp-s-'+status);
744
                        _prevStatus = status;
745
                }
746
        },
747

    
748

    
749
        /*
750
                "Private" helpers that aren't private at all
751
         */
752
        _addClassToMFP: function(cName) {
753
                mfp.bgOverlay.addClass(cName);
754
                mfp.wrap.addClass(cName);
755
        },
756
        _removeClassFromMFP: function(cName) {
757
                this.bgOverlay.removeClass(cName);
758
                mfp.wrap.removeClass(cName);
759
        },
760
        _hasScrollBar: function(winHeight) {
761
                return (  (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) );
762
        },
763
        _parseMarkup: function(template, values, item) {
764
                var arr;
765
                if(item.data) {
766
                        values = $.extend(item.data, values);
767
                }
768
                _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] );
769

    
770
                $.each(values, function(key, value) {
771
                        if(value === undefined || value === false) {
772
                                return true;
773
                        }
774
                        arr = key.split('_');
775
                        if(arr.length > 1) {
776
                                var el = template.find(EVENT_NS + '-'+arr[0]);
777

    
778
                                if(el.length > 0) {
779
                                        var attr = arr[1];
780
                                        if(attr === 'replaceWith') {
781
                                                if(el[0] !== value[0]) {
782
                                                        el.replaceWith(value);
783
                                                }
784
                                        } else if(attr === 'img') {
785
                                                if(el.is('img')) {
786
                                                        el.attr('src', value);
787
                                                } else {
788
                                                        el.replaceWith( '<img src="'+value+'" class="' + el.attr('class') + '" />' );
789
                                                }
790
                                        } else {
791
                                                el.attr(arr[1], value);
792
                                        }
793
                                }
794

    
795
                        } else {
796
                                template.find(EVENT_NS + '-'+key).html(value);
797
                        }
798
                });
799
        },
800

    
801
        _getScrollbarSize: function() {
802
                // thx David
803
                if(mfp.scrollbarSize === undefined) {
804
                        var scrollDiv = document.createElement("div");
805
                        scrollDiv.id = "mfp-sbm";
806
                        scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
807
                        document.body.appendChild(scrollDiv);
808
                        mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
809
                        document.body.removeChild(scrollDiv);
810
                }
811
                return mfp.scrollbarSize;
812
        }
813

    
814
}; /* MagnificPopup core prototype end */
815

    
816

    
817

    
818

    
819
/**
820
 * Public static functions
821
 */
822
$.magnificPopup = {
823
        instance: null,
824
        proto: MagnificPopup.prototype,
825
        modules: [],
826

    
827
        open: function(options, index) {
828
                _checkInstance();        
829

    
830
                if(!options) 
831
                        options = {};
832

    
833
                options.isObj = true;
834
                options.index = index || 0;
835
                return this.instance.open(options);
836
        },
837

    
838
        close: function() {
839
                return $.magnificPopup.instance.close();
840
        },
841

    
842
        registerModule: function(name, module) {
843
                if(module.options) {
844
                        $.magnificPopup.defaults[name] = module.options;
845
                }
846
                $.extend(this.proto, module.proto);                        
847
                this.modules.push(name);
848
        },
849

    
850
        defaults: {   
851

    
852
                // Info about options is in docs:
853
                // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options
854
                
855
                disableOn: 0,        
856

    
857
                key: null,
858

    
859
                midClick: false,
860

    
861
                mainClass: '',
862

    
863
                preloader: true,
864

    
865
                focus: '', // CSS selector of input to focus after popup is opened
866
                
867
                closeOnContentClick: false,
868

    
869
                closeOnBgClick: true,
870

    
871
                closeBtnInside: true, 
872

    
873
                showCloseBtn: true,
874

    
875
                enableEscapeKey: true,
876

    
877
                modal: false,
878

    
879
                alignTop: false,
880
        
881
                removalDelay: 0,
882
                
883
                fixedContentPos: 'auto', 
884
        
885
                fixedBgPos: 'auto',
886

    
887
                overflowY: 'auto',
888

    
889
                closeMarkup: '<button title="%title%" type="button" class="mfp-close">&times;</button>',
890

    
891
                tClose: 'Close (Esc)',
892

    
893
                tLoading: 'Loading...'
894

    
895
        }
896
};
897

    
898

    
899

    
900
$.fn.magnificPopup = function(options) {
901
        _checkInstance();
902

    
903
        var jqEl = $(this);
904

    
905
        // We call some API method of first param is a string
906
        if (typeof options === "string" ) {
907

    
908
                if(options === 'open') {
909
                        var items,
910
                                itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup,
911
                                index = parseInt(arguments[1], 10) || 0;
912

    
913
                        if(itemOpts.items) {
914
                                items = itemOpts.items[index];
915
                        } else {
916
                                items = jqEl;
917
                                if(itemOpts.delegate) {
918
                                        items = items.find(itemOpts.delegate);
919
                                }
920
                                items = items.eq( index );
921
                        }
922
                        mfp._openClick({mfpEl:items}, jqEl, itemOpts);
923
                } else {
924
                        if(mfp.isOpen)
925
                                mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
926
                }
927

    
928
        } else {
929

    
930
                /*
931
                 * As Zepto doesn't support .data() method for objects 
932
                 * and it works only in normal browsers
933
                 * we assign "options" object directly to the DOM element. FTW!
934
                 */
935
                if(_isJQ) {
936
                        jqEl.data('magnificPopup', options);
937
                } else {
938
                        jqEl[0].magnificPopup = options;
939
                }
940

    
941
                mfp.addGroup(jqEl, options);
942

    
943
        }
944
        return jqEl;
945
};
946

    
947

    
948
//Quick benchmark
949
/*
950
var start = performance.now(),
951
        i,
952
        rounds = 1000;
953

954
for(i = 0; i < rounds; i++) {
955

956
}
957
console.log('Test #1:', performance.now() - start);
958

959
start = performance.now();
960
for(i = 0; i < rounds; i++) {
961

962
}
963
console.log('Test #2:', performance.now() - start);
964
*/
965

    
966

    
967
/*>>core*/
968

    
969
/*>>inline*/
970

    
971
var INLINE_NS = 'inline',
972
        _hiddenClass,
973
        _inlinePlaceholder, 
974
        _lastInlineElement,
975
        _putInlineElementsBack = function() {
976
                if(_lastInlineElement) {
977
                        _inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach();
978
                        _lastInlineElement = null;
979
                }
980
        };
981

    
982
$.magnificPopup.registerModule(INLINE_NS, {
983
        options: {
984
                hiddenClass: 'hide', // will be appended with `mfp-` prefix
985
                markup: '',
986
                tNotFound: 'Content not found'
987
        },
988
        proto: {
989

    
990
                initInline: function() {
991
                        mfp.types.push(INLINE_NS);
992

    
993
                        _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() {
994
                                _putInlineElementsBack();
995
                        });
996
                },
997

    
998
                getInline: function(item, template) {
999

    
1000
                        _putInlineElementsBack();
1001

    
1002
                        if(item.src) {
1003
                                var inlineSt = mfp.st.inline,
1004
                                        el = $(item.src);
1005

    
1006
                                if(el.length) {
1007

    
1008
                                        // If target element has parent - we replace it with placeholder and put it back after popup is closed
1009
                                        var parent = el[0].parentNode;
1010
                                        if(parent && parent.tagName) {
1011
                                                if(!_inlinePlaceholder) {
1012
                                                        _hiddenClass = inlineSt.hiddenClass;
1013
                                                        _inlinePlaceholder = _getEl(_hiddenClass);
1014
                                                        _hiddenClass = 'mfp-'+_hiddenClass;
1015
                                                }
1016
                                                // replace target inline element with placeholder
1017
                                                _lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass);
1018
                                        }
1019

    
1020
                                        mfp.updateStatus('ready');
1021
                                } else {
1022
                                        mfp.updateStatus('error', inlineSt.tNotFound);
1023
                                        el = $('<div>');
1024
                                }
1025

    
1026
                                item.inlineElement = el;
1027
                                return el;
1028
                        }
1029

    
1030
                        mfp.updateStatus('ready');
1031
                        mfp._parseMarkup(template, {}, item);
1032
                        return template;
1033
                }
1034
        }
1035
});
1036

    
1037
/*>>inline*/
1038

    
1039
/*>>ajax*/
1040
var AJAX_NS = 'ajax',
1041
        _ajaxCur,
1042
        _removeAjaxCursor = function() {
1043
                if(_ajaxCur) {
1044
                        _body.removeClass(_ajaxCur);
1045
                }
1046
        };
1047

    
1048
$.magnificPopup.registerModule(AJAX_NS, {
1049

    
1050
        options: {
1051
                settings: null,
1052
                cursor: 'mfp-ajax-cur',
1053
                tError: '<a href="%url%">The content</a> could not be loaded.'
1054
        },
1055

    
1056
        proto: {
1057
                initAjax: function() {
1058
                        mfp.types.push(AJAX_NS);
1059
                        _ajaxCur = mfp.st.ajax.cursor;
1060

    
1061
                        _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, function() {
1062
                                _removeAjaxCursor();
1063
                                if(mfp.req) {
1064
                                        mfp.req.abort();
1065
                                }
1066
                        });
1067
                },
1068

    
1069
                getAjax: function(item) {
1070

    
1071
                        if(_ajaxCur)
1072
                                _body.addClass(_ajaxCur);
1073

    
1074
                        mfp.updateStatus('loading');
1075

    
1076
                        var opts = $.extend({
1077
                                url: item.src,
1078
                                success: function(data, textStatus, jqXHR) {
1079
                                        var temp = {
1080
                                                data:data,
1081
                                                xhr:jqXHR
1082
                                        };
1083

    
1084
                                        _mfpTrigger('ParseAjax', temp);
1085

    
1086
                                        mfp.appendContent( $(temp.data), AJAX_NS );
1087

    
1088
                                        item.finished = true;
1089

    
1090
                                        _removeAjaxCursor();
1091

    
1092
                                        _setFocus();
1093

    
1094
                                        setTimeout(function() {
1095
                                                mfp.wrap.addClass(READY_CLASS);
1096
                                        }, 16);
1097

    
1098
                                        mfp.updateStatus('ready');
1099

    
1100
                                        _mfpTrigger('AjaxContentAdded');
1101
                                },
1102
                                error: function() {
1103
                                        _removeAjaxCursor();
1104
                                        item.finished = item.loadError = true;
1105
                                        mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src));
1106
                                }
1107
                        }, mfp.st.ajax.settings);
1108

    
1109
                        mfp.req = $.ajax(opts);
1110

    
1111
                        return '';
1112
                }
1113
        }
1114
});
1115

    
1116

    
1117

    
1118

    
1119

    
1120
        
1121

    
1122
/*>>ajax*/
1123

    
1124
/*>>image*/
1125
var _imgInterval,
1126
        _getTitle = function(item) {
1127
                if(item.data && item.data.title !== undefined) 
1128
                        return item.data.title;
1129

    
1130
                var src = mfp.st.image.titleSrc;
1131

    
1132
                if(src) {
1133
                        if($.isFunction(src)) {
1134
                                return src.call(mfp, item);
1135
                        } else if(item.el) {
1136
                                return item.el.attr(src) || '';
1137
                        }
1138
                }
1139
                return '';
1140
        };
1141

    
1142
$.magnificPopup.registerModule('image', {
1143

    
1144
        options: {
1145
                markup: '<div class="mfp-figure">'+
1146
                                        '<div class="mfp-close"></div>'+
1147
                                        '<div class="mfp-img"></div>'+
1148
                                        '<div class="mfp-bottom-bar">'+
1149
                                                '<div class="mfp-title"></div>'+
1150
                                                '<div class="mfp-counter"></div>'+
1151
                                        '</div>'+
1152
                                '</div>',
1153
                cursor: 'mfp-zoom-out-cur',
1154
                titleSrc: 'title', 
1155
                verticalFit: true,
1156
                tError: '<a href="%url%">The image</a> could not be loaded.'
1157
        },
1158

    
1159
        proto: {
1160
                initImage: function() {
1161
                        var imgSt = mfp.st.image,
1162
                                ns = '.image';
1163

    
1164
                        mfp.types.push('image');
1165

    
1166
                        _mfpOn(OPEN_EVENT+ns, function() {
1167
                                if(mfp.currItem.type === 'image' && imgSt.cursor) {
1168
                                        _body.addClass(imgSt.cursor);
1169
                                }
1170
                        });
1171

    
1172
                        _mfpOn(CLOSE_EVENT+ns, function() {
1173
                                if(imgSt.cursor) {
1174
                                        _body.removeClass(imgSt.cursor);
1175
                                }
1176
                                _window.off('resize' + EVENT_NS);
1177
                        });
1178

    
1179
                        _mfpOn('Resize'+ns, mfp.resizeImage);
1180
                        if(mfp.isLowIE) {
1181
                                _mfpOn('AfterChange', mfp.resizeImage);
1182
                        }
1183
                },
1184
                resizeImage: function() {
1185
                        var item = mfp.currItem;
1186
                        if(!item || !item.img) return;
1187

    
1188
                        if(mfp.st.image.verticalFit) {
1189
                                var decr = 0;
1190
                                // fix box-sizing in ie7/8
1191
                                if(mfp.isLowIE) {
1192
                                        decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10);
1193
                                }
1194
                                item.img.css('max-height', mfp.wH-decr);
1195
                        }
1196
                },
1197
                _onImageHasSize: function(item) {
1198
                        if(item.img) {
1199
                                
1200
                                item.hasSize = true;
1201

    
1202
                                if(_imgInterval) {
1203
                                        clearInterval(_imgInterval);
1204
                                }
1205
                                
1206
                                item.isCheckingImgSize = false;
1207

    
1208
                                _mfpTrigger('ImageHasSize', item);
1209

    
1210
                                if(item.imgHidden) {
1211
                                        if(mfp.content)
1212
                                                mfp.content.removeClass('mfp-loading');
1213
                                        
1214
                                        item.imgHidden = false;
1215
                                }
1216

    
1217
                        }
1218
                },
1219

    
1220
                /**
1221
                 * Function that loops until the image has size to display elements that rely on it asap
1222
                 */
1223
                findImageSize: function(item) {
1224

    
1225
                        var counter = 0,
1226
                                img = item.img[0],
1227
                                mfpSetInterval = function(delay) {
1228

    
1229
                                        if(_imgInterval) {
1230
                                                clearInterval(_imgInterval);
1231
                                        }
1232
                                        // decelerating interval that checks for size of an image
1233
                                        _imgInterval = setInterval(function() {
1234
                                                if(img.naturalWidth > 0) {
1235
                                                        mfp._onImageHasSize(item);
1236
                                                        return;
1237
                                                }
1238

    
1239
                                                if(counter > 200) {
1240
                                                        clearInterval(_imgInterval);
1241
                                                }
1242

    
1243
                                                counter++;
1244
                                                if(counter === 3) {
1245
                                                        mfpSetInterval(10);
1246
                                                } else if(counter === 40) {
1247
                                                        mfpSetInterval(50);
1248
                                                } else if(counter === 100) {
1249
                                                        mfpSetInterval(500);
1250
                                                }
1251
                                        }, delay);
1252
                                };
1253

    
1254
                        mfpSetInterval(1);
1255
                },
1256

    
1257
                getImage: function(item, template) {
1258

    
1259
                        var guard = 0,
1260

    
1261
                                // image load complete handler
1262
                                onLoadComplete = function() {
1263
                                        if(item) {
1264
                                                if (item.img[0].complete) {
1265
                                                        item.img.off('.mfploader');
1266
                                                        
1267
                                                        if(item === mfp.currItem){
1268
                                                                mfp._onImageHasSize(item);
1269

    
1270
                                                                mfp.updateStatus('ready');
1271
                                                        }
1272

    
1273
                                                        item.hasSize = true;
1274
                                                        item.loaded = true;
1275

    
1276
                                                        _mfpTrigger('ImageLoadComplete');
1277
                                                        
1278
                                                }
1279
                                                else {
1280
                                                        // if image complete check fails 200 times (20 sec), we assume that there was an error.
1281
                                                        guard++;
1282
                                                        if(guard < 200) {
1283
                                                                setTimeout(onLoadComplete,100);
1284
                                                        } else {
1285
                                                                onLoadError();
1286
                                                        }
1287
                                                }
1288
                                        }
1289
                                },
1290

    
1291
                                // image error handler
1292
                                onLoadError = function() {
1293
                                        if(item) {
1294
                                                item.img.off('.mfploader');
1295
                                                if(item === mfp.currItem){
1296
                                                        mfp._onImageHasSize(item);
1297
                                                        mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
1298
                                                }
1299

    
1300
                                                item.hasSize = true;
1301
                                                item.loaded = true;
1302
                                                item.loadError = true;
1303
                                        }
1304
                                },
1305
                                imgSt = mfp.st.image;
1306

    
1307

    
1308
                        var el = template.find('.mfp-img');
1309
                        if(el.length) {
1310
                                var img = document.createElement('img');
1311
                                img.className = 'mfp-img';
1312
                                item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError);
1313
                                img.src = item.src;
1314

    
1315
                                // without clone() "error" event is not firing when IMG is replaced by new IMG
1316
                                // TODO: find a way to avoid such cloning
1317
                                if(el.is('img')) {
1318
                                        item.img = item.img.clone();
1319
                                }
1320
                                if(item.img[0].naturalWidth > 0) {
1321
                                        item.hasSize = true;
1322
                                }
1323
                        }
1324

    
1325
                        mfp._parseMarkup(template, {
1326
                                title: _getTitle(item),
1327
                                img_replaceWith: item.img
1328
                        }, item);
1329

    
1330
                        mfp.resizeImage();
1331

    
1332
                        if(item.hasSize) {
1333
                                if(_imgInterval) clearInterval(_imgInterval);
1334

    
1335
                                if(item.loadError) {
1336
                                        template.addClass('mfp-loading');
1337
                                        mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
1338
                                } else {
1339
                                        template.removeClass('mfp-loading');
1340
                                        mfp.updateStatus('ready');
1341
                                }
1342
                                return template;
1343
                        }
1344

    
1345
                        mfp.updateStatus('loading');
1346
                        item.loading = true;
1347

    
1348
                        if(!item.hasSize) {
1349
                                item.imgHidden = true;
1350
                                template.addClass('mfp-loading');
1351
                                mfp.findImageSize(item);
1352
                        } 
1353

    
1354
                        return template;
1355
                }
1356
        }
1357
});
1358

    
1359

    
1360

    
1361
/*>>image*/
1362

    
1363
/*>>zoom*/
1364
var hasMozTransform,
1365
        getHasMozTransform = function() {
1366
                if(hasMozTransform === undefined) {
1367
                        hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
1368
                }
1369
                return hasMozTransform;                
1370
        };
1371

    
1372
$.magnificPopup.registerModule('zoom', {
1373

    
1374
        options: {
1375
                enabled: false,
1376
                easing: 'ease-in-out',
1377
                duration: 300,
1378
                opener: function(element) {
1379
                        return element.is('img') ? element : element.find('img');
1380
                }
1381
        },
1382

    
1383
        proto: {
1384

    
1385
                initZoom: function() {
1386
                        var zoomSt = mfp.st.zoom,
1387
                                ns = '.zoom';
1388
                                
1389
                        if(!zoomSt.enabled || !mfp.supportsTransition) {
1390
                                return;
1391
                        }
1392

    
1393
                        var duration = zoomSt.duration,
1394
                                getElToAnimate = function(image) {
1395
                                        var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
1396
                                                transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
1397
                                                cssObj = {
1398
                                                        position: 'fixed',
1399
                                                        zIndex: 9999,
1400
                                                        left: 0,
1401
                                                        top: 0,
1402
                                                        '-webkit-backface-visibility': 'hidden'
1403
                                                },
1404
                                                t = 'transition';
1405

    
1406
                                        cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;
1407

    
1408
                                        newImg.css(cssObj);
1409
                                        return newImg;
1410
                                },
1411
                                showMainContent = function() {
1412
                                        mfp.content.css('visibility', 'visible');
1413
                                },
1414
                                openTimeout,
1415
                                animatedImg;
1416

    
1417
                        _mfpOn('BuildControls'+ns, function() {
1418
                                if(mfp._allowZoom()) {
1419

    
1420
                                        clearTimeout(openTimeout);
1421
                                        mfp.content.css('visibility', 'hidden');
1422

    
1423
                                        // Basically, all code below does is clones existing image, puts in on top of the current one and animated it
1424
                                        
1425
                                        image = mfp._getItemToZoom();
1426

    
1427
                                        if(!image) {
1428
                                                showMainContent();
1429
                                                return;
1430
                                        }
1431

    
1432
                                        animatedImg = getElToAnimate(image); 
1433
                                        
1434
                                        animatedImg.css( mfp._getOffset() );
1435

    
1436
                                        mfp.wrap.append(animatedImg);
1437

    
1438
                                        openTimeout = setTimeout(function() {
1439
                                                animatedImg.css( mfp._getOffset( true ) );
1440
                                                openTimeout = setTimeout(function() {
1441

    
1442
                                                        showMainContent();
1443

    
1444
                                                        setTimeout(function() {
1445
                                                                animatedImg.remove();
1446
                                                                image = animatedImg = null;
1447
                                                                _mfpTrigger('ZoomAnimationEnded');
1448
                                                        }, 16); // avoid blink when switching images 
1449

    
1450
                                                }, duration); // this timeout equals animation duration
1451

    
1452
                                        }, 16); // by adding this timeout we avoid short glitch at the beginning of animation
1453

    
1454

    
1455
                                        // Lots of timeouts...
1456
                                }
1457
                        });
1458
                        _mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
1459
                                if(mfp._allowZoom()) {
1460

    
1461
                                        clearTimeout(openTimeout);
1462

    
1463
                                        mfp.st.removalDelay = duration;
1464

    
1465
                                        if(!image) {
1466
                                                image = mfp._getItemToZoom();
1467
                                                if(!image) {
1468
                                                        return;
1469
                                                }
1470
                                                animatedImg = getElToAnimate(image);
1471
                                        }
1472
                                        
1473
                                        
1474
                                        animatedImg.css( mfp._getOffset(true) );
1475
                                        mfp.wrap.append(animatedImg);
1476
                                        mfp.content.css('visibility', 'hidden');
1477
                                        
1478
                                        setTimeout(function() {
1479
                                                animatedImg.css( mfp._getOffset() );
1480
                                        }, 16);
1481
                                }
1482

    
1483
                        });
1484

    
1485
                        _mfpOn(CLOSE_EVENT+ns, function() {
1486
                                if(mfp._allowZoom()) {
1487
                                        showMainContent();
1488
                                        if(animatedImg) {
1489
                                                animatedImg.remove();
1490
                                        }
1491
                                }        
1492
                        });
1493
                },
1494

    
1495
                _allowZoom: function() {
1496
                        return mfp.currItem.type === 'image';
1497
                },
1498

    
1499
                _getItemToZoom: function() {
1500
                        if(mfp.currItem.hasSize) {
1501
                                return mfp.currItem.img;
1502
                        } else {
1503
                                return false;
1504
                        }
1505
                },
1506

    
1507
                // Get element postion relative to viewport
1508
                _getOffset: function(isLarge) {
1509
                        var el;
1510
                        if(isLarge) {
1511
                                el = mfp.currItem.img;
1512
                        } else {
1513
                                el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
1514
                        }
1515

    
1516
                        var offset = el.offset();
1517
                        var paddingTop = parseInt(el.css('padding-top'),10);
1518
                        var paddingBottom = parseInt(el.css('padding-bottom'),10);
1519
                        offset.top -= ( $(window).scrollTop() - paddingTop );
1520

    
1521

    
1522
                        /*
1523
                        
1524
                        Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.
1525

1526
                         */
1527
                        var obj = {
1528
                                width: el.width(),
1529
                                // fix Zepto height+padding issue
1530
                                height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
1531
                        };
1532

    
1533
                        // I hate to do this, but there is no another option
1534
                        if( getHasMozTransform() ) {
1535
                                obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
1536
                        } else {
1537
                                obj.left = offset.left;
1538
                                obj.top = offset.top;
1539
                        }
1540
                        return obj;
1541
                }
1542

    
1543
        }
1544
});
1545

    
1546

    
1547

    
1548
/*>>zoom*/
1549

    
1550
/*>>iframe*/
1551

    
1552
var IFRAME_NS = 'iframe',
1553
        _emptyPage = '//about:blank',
1554
        
1555
        _fixIframeBugs = function(isShowing) {
1556
                if(mfp.currTemplate[IFRAME_NS]) {
1557
                        var el = mfp.currTemplate[IFRAME_NS].find('iframe');
1558
                        if(el.length) { 
1559
                                // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
1560
                                if(!isShowing) {
1561
                                        el[0].src = _emptyPage;
1562
                                }
1563

    
1564
                                // IE8 black screen bug fix
1565
                                if(mfp.isIE8) {
1566
                                        el.css('display', isShowing ? 'block' : 'none');
1567
                                }
1568
                        }
1569
                }
1570
        };
1571

    
1572
$.magnificPopup.registerModule(IFRAME_NS, {
1573

    
1574
        options: {
1575
                markup: '<div class="mfp-iframe-scaler">'+
1576
                                        '<div class="mfp-close"></div>'+
1577
                                        '<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+
1578
                                '</div>',
1579

    
1580
                srcAction: 'iframe_src',
1581

    
1582
                // we don't care and support only one default type of URL by default
1583
                patterns: {
1584
                        youtube: {
1585
                                index: 'youtube.com', 
1586
                                id: 'v=', 
1587
                                src: '//www.youtube.com/embed/%id%?autoplay=1'
1588
                        },
1589
                        vimeo: {
1590
                                index: 'vimeo.com/',
1591
                                id: '/',
1592
                                src: '//player.vimeo.com/video/%id%?autoplay=1'
1593
                        },
1594
                        gmaps: {
1595
                                index: '//maps.google.',
1596
                                src: '%id%&output=embed'
1597
                        }
1598
                }
1599
        },
1600

    
1601
        proto: {
1602
                initIframe: function() {
1603
                        mfp.types.push(IFRAME_NS);
1604

    
1605
                        _mfpOn('BeforeChange', function(e, prevType, newType) {
1606
                                if(prevType !== newType) {
1607
                                        if(prevType === IFRAME_NS) {
1608
                                                _fixIframeBugs(); // iframe if removed
1609
                                        } else if(newType === IFRAME_NS) {
1610
                                                _fixIframeBugs(true); // iframe is showing
1611
                                        } 
1612
                                }// else {
1613
                                        // iframe source is switched, don't do anything
1614
                                //}
1615
                        });
1616

    
1617
                        _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
1618
                                _fixIframeBugs();
1619
                        });
1620
                },
1621

    
1622
                getIframe: function(item, template) {
1623
                        var embedSrc = item.src;
1624
                        var iframeSt = mfp.st.iframe;
1625
                                
1626
                        $.each(iframeSt.patterns, function() {
1627
                                if(embedSrc.indexOf( this.index ) > -1) {
1628
                                        if(this.id) {
1629
                                                if(typeof this.id === 'string') {
1630
                                                        embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
1631
                                                } else {
1632
                                                        embedSrc = this.id.call( this, embedSrc );
1633
                                                }
1634
                                        }
1635
                                        embedSrc = this.src.replace('%id%', embedSrc );
1636
                                        return false; // break;
1637
                                }
1638
                        });
1639
                        
1640
                        var dataObj = {};
1641
                        if(iframeSt.srcAction) {
1642
                                dataObj[iframeSt.srcAction] = embedSrc;
1643
                        }
1644
                        mfp._parseMarkup(template, dataObj, item);
1645

    
1646
                        mfp.updateStatus('ready');
1647

    
1648
                        return template;
1649
                }
1650
        }
1651
});
1652

    
1653

    
1654

    
1655
/*>>iframe*/
1656

    
1657
/*>>gallery*/
1658
/**
1659
 * Get looped index depending on number of slides
1660
 */
1661
var _getLoopedId = function(index) {
1662
                var numSlides = mfp.items.length;
1663
                if(index > numSlides - 1) {
1664
                        return index - numSlides;
1665
                } else  if(index < 0) {
1666
                        return numSlides + index;
1667
                }
1668
                return index;
1669
        },
1670
        _replaceCurrTotal = function(text, curr, total) {
1671
                return text.replace('%curr%', curr + 1).replace('%total%', total);
1672
        };
1673

    
1674
$.magnificPopup.registerModule('gallery', {
1675

    
1676
        options: {
1677
                enabled: false,
1678
                arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
1679
                preload: [0,2],
1680
                navigateByImgClick: true,
1681
                arrows: true,
1682

    
1683
                tPrev: 'Previous (Left arrow key)',
1684
                tNext: 'Next (Right arrow key)',
1685
                tCounter: '%curr% of %total%'
1686
        },
1687

    
1688
        proto: {
1689
                initGallery: function() {
1690

    
1691
                        var gSt = mfp.st.gallery,
1692
                                ns = '.mfp-gallery',
1693
                                supportsFastClick = Boolean($.fn.mfpFastClick);
1694

    
1695
                        mfp.direction = true; // true - next, false - prev
1696
                        
1697
                        if(!gSt || !gSt.enabled ) return false;
1698

    
1699
                        _wrapClasses += ' mfp-gallery';
1700

    
1701
                        _mfpOn(OPEN_EVENT+ns, function() {
1702

    
1703
                                if(gSt.navigateByImgClick) {
1704
                                        mfp.wrap.on('click'+ns, '.mfp-img', function() {
1705
                                                if(mfp.items.length > 1) {
1706
                                                        mfp.next();
1707
                                                        return false;
1708
                                                }
1709
                                        });
1710
                                }
1711

    
1712
                                _document.on('keydown'+ns, function(e) {
1713
                                        if (e.keyCode === 37) {
1714
                                                mfp.prev();
1715
                                        } else if (e.keyCode === 39) {
1716
                                                mfp.next();
1717
                                        }
1718
                                });
1719
                        });
1720

    
1721
                        _mfpOn('UpdateStatus'+ns, function(e, data) {
1722
                                if(data.text) {
1723
                                        data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
1724
                                }
1725
                        });
1726

    
1727
                        _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
1728
                                var l = mfp.items.length;
1729
                                values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
1730
                        });
1731

    
1732
                        _mfpOn('BuildControls' + ns, function() {
1733
                                if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
1734
                                        var markup = gSt.arrowMarkup,
1735
                                                arrowLeft = mfp.arrowLeft = $( markup.replace('%title%', gSt.tPrev).replace('%dir%', 'left') ).addClass(PREVENT_CLOSE_CLASS),                        
1736
                                                arrowRight = mfp.arrowRight = $( markup.replace('%title%', gSt.tNext).replace('%dir%', 'right') ).addClass(PREVENT_CLOSE_CLASS);
1737

    
1738
                                        var eName = supportsFastClick ? 'mfpFastClick' : 'click';
1739
                                        arrowLeft[eName](function() {
1740
                                                mfp.prev();
1741
                                        });                        
1742
                                        arrowRight[eName](function() {
1743
                                                mfp.next();
1744
                                        });        
1745

    
1746
                                        // Polyfill for :before and :after (adds elements with classes mfp-a and mfp-b)
1747
                                        if(mfp.isIE7) {
1748
                                                _getEl('b', arrowLeft[0], false, true);
1749
                                                _getEl('a', arrowLeft[0], false, true);
1750
                                                _getEl('b', arrowRight[0], false, true);
1751
                                                _getEl('a', arrowRight[0], false, true);
1752
                                        }
1753

    
1754
                                        mfp.container.append(arrowLeft.add(arrowRight));
1755
                                }
1756
                        });
1757

    
1758
                        _mfpOn(CHANGE_EVENT+ns, function() {
1759
                                if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);
1760

    
1761
                                mfp._preloadTimeout = setTimeout(function() {
1762
                                        mfp.preloadNearbyImages();
1763
                                        mfp._preloadTimeout = null;
1764
                                }, 16);                
1765
                        });
1766

    
1767

    
1768
                        _mfpOn(CLOSE_EVENT+ns, function() {
1769
                                _document.off(ns);
1770
                                mfp.wrap.off('click'+ns);
1771
                        
1772
                                if(mfp.arrowLeft && supportsFastClick) {
1773
                                        mfp.arrowLeft.add(mfp.arrowRight).destroyMfpFastClick();
1774
                                }
1775
                                mfp.arrowRight = mfp.arrowLeft = null;
1776
                        });
1777

    
1778
                }, 
1779
                next: function() {
1780
                        mfp.direction = true;
1781
                        mfp.index = _getLoopedId(mfp.index + 1);
1782
                        mfp.updateItemHTML();
1783
                },
1784
                prev: function() {
1785
                        mfp.direction = false;
1786
                        mfp.index = _getLoopedId(mfp.index - 1);
1787
                        mfp.updateItemHTML();
1788
                },
1789
                goTo: function(newIndex) {
1790
                        mfp.direction = (newIndex >= mfp.index);
1791
                        mfp.index = newIndex;
1792
                        mfp.updateItemHTML();
1793
                },
1794
                preloadNearbyImages: function() {
1795
                        var p = mfp.st.gallery.preload,
1796
                                preloadBefore = Math.min(p[0], mfp.items.length),
1797
                                preloadAfter = Math.min(p[1], mfp.items.length),
1798
                                i;
1799

    
1800
                        for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
1801
                                mfp._preloadItem(mfp.index+i);
1802
                        }
1803
                        for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
1804
                                mfp._preloadItem(mfp.index-i);
1805
                        }
1806
                },
1807
                _preloadItem: function(index) {
1808
                        index = _getLoopedId(index);
1809

    
1810
                        if(mfp.items[index].preloaded) {
1811
                                return;
1812
                        }
1813

    
1814
                        var item = mfp.items[index];
1815
                        if(!item.parsed) {
1816
                                item = mfp.parseEl( index );
1817
                        }
1818

    
1819
                        _mfpTrigger('LazyLoad', item);
1820

    
1821
                        if(item.type === 'image') {
1822
                                item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
1823
                                        item.hasSize = true;
1824
                                }).on('error.mfploader', function() {
1825
                                        item.hasSize = true;
1826
                                        item.loadError = true;
1827
                                        _mfpTrigger('LazyLoadError', item);
1828
                                }).attr('src', item.src);
1829
                        }
1830

    
1831

    
1832
                        item.preloaded = true;
1833
                }
1834
        }
1835
});
1836

    
1837
/*
1838
Touch Support that might be implemented some day
1839

1840
addSwipeGesture: function() {
1841
        var startX,
1842
                moved,
1843
                multipleTouches;
1844

1845
                return;
1846

1847
        var namespace = '.mfp',
1848
                addEventNames = function(pref, down, move, up, cancel) {
1849
                        mfp._tStart = pref + down + namespace;
1850
                        mfp._tMove = pref + move + namespace;
1851
                        mfp._tEnd = pref + up + namespace;
1852
                        mfp._tCancel = pref + cancel + namespace;
1853
                };
1854

1855
        if(window.navigator.msPointerEnabled) {
1856
                addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel');
1857
        } else if('ontouchstart' in window) {
1858
                addEventNames('touch', 'start', 'move', 'end', 'cancel');
1859
        } else {
1860
                return;
1861
        }
1862
        _window.on(mfp._tStart, function(e) {
1863
                var oE = e.originalEvent;
1864
                multipleTouches = moved = false;
1865
                startX = oE.pageX || oE.changedTouches[0].pageX;
1866
        }).on(mfp._tMove, function(e) {
1867
                if(e.originalEvent.touches.length > 1) {
1868
                        multipleTouches = e.originalEvent.touches.length;
1869
                } else {
1870
                        //e.preventDefault();
1871
                        moved = true;
1872
                }
1873
        }).on(mfp._tEnd + ' ' + mfp._tCancel, function(e) {
1874
                if(moved && !multipleTouches) {
1875
                        var oE = e.originalEvent,
1876
                                diff = startX - (oE.pageX || oE.changedTouches[0].pageX);
1877

1878
                        if(diff > 20) {
1879
                                mfp.next();
1880
                        } else if(diff < -20) {
1881
                                mfp.prev();
1882
                        }
1883
                }
1884
        });
1885
},
1886
*/
1887

    
1888

    
1889
/*>>gallery*/
1890

    
1891
/*>>retina*/
1892

    
1893
var RETINA_NS = 'retina';
1894

    
1895
$.magnificPopup.registerModule(RETINA_NS, {
1896
        options: {
1897
                replaceSrc: function(item) {
1898
                        return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
1899
                },
1900
                ratio: 1 // Function or number.  Set to 1 to disable.
1901
        },
1902
        proto: {
1903
                initRetina: function() {
1904
                        if(window.devicePixelRatio > 1) {
1905

    
1906
                                var st = mfp.st.retina,
1907
                                        ratio = st.ratio;
1908

    
1909
                                ratio = !isNaN(ratio) ? ratio : ratio();
1910

    
1911
                                if(ratio > 1) {
1912
                                        _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
1913
                                                item.img.css({
1914
                                                        'max-width': item.img[0].naturalWidth / ratio,
1915
                                                        'width': '100%'
1916
                                                });
1917
                                        });
1918
                                        _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
1919
                                                item.src = st.replaceSrc(item, ratio);
1920
                                        });
1921
                                }
1922
                        }
1923

    
1924
                }
1925
        }
1926
});
1927

    
1928
/*>>retina*/
1929

    
1930
/*>>fastclick*/
1931
/**
1932
 * FastClick event implementation. (removes 300ms delay on touch devices)
1933
 * Based on https://developers.google.com/mobile/articles/fast_buttons
1934
 *
1935
 * You may use it outside the Magnific Popup by calling just:
1936
 *
1937
 * $('.your-el').mfpFastClick(function() {
1938
 *     console.log('Clicked!');
1939
 * });
1940
 *
1941
 * To unbind:
1942
 * $('.your-el').destroyMfpFastClick();
1943
 * 
1944
 * 
1945
 * Note that it's a very basic and simple implementation, it blocks ghost click on the same element where it was bound.
1946
 * If you need something more advanced, use plugin by FT Labs https://github.com/ftlabs/fastclick
1947
 * 
1948
 */
1949

    
1950
(function() {
1951
        var ghostClickDelay = 1000,
1952
                supportsTouch = 'ontouchstart' in window,
1953
                unbindTouchMove = function() {
1954
                        _window.off('touchmove'+ns+' touchend'+ns);
1955
                },
1956
                eName = 'mfpFastClick',
1957
                ns = '.'+eName;
1958

    
1959

    
1960
        // As Zepto.js doesn't have an easy way to add custom events (like jQuery), so we implement it in this way
1961
        $.fn.mfpFastClick = function(callback) {
1962

    
1963
                return $(this).each(function() {
1964

    
1965
                        var elem = $(this),
1966
                                lock;
1967

    
1968
                        if( supportsTouch ) {
1969

    
1970
                                var timeout,
1971
                                        startX,
1972
                                        startY,
1973
                                        pointerMoved,
1974
                                        point,
1975
                                        numPointers;
1976

    
1977
                                elem.on('touchstart' + ns, function(e) {
1978
                                        pointerMoved = false;
1979
                                        numPointers = 1;
1980

    
1981
                                        point = e.originalEvent ? e.originalEvent.touches[0] : e.touches[0];
1982
                                        startX = point.clientX;
1983
                                        startY = point.clientY;
1984

    
1985
                                        _window.on('touchmove'+ns, function(e) {
1986
                                                point = e.originalEvent ? e.originalEvent.touches : e.touches;
1987
                                                numPointers = point.length;
1988
                                                point = point[0];
1989
                                                if (Math.abs(point.clientX - startX) > 10 ||
1990
                                                        Math.abs(point.clientY - startY) > 10) {
1991
                                                        pointerMoved = true;
1992
                                                        unbindTouchMove();
1993
                                                }
1994
                                        }).on('touchend'+ns, function(e) {
1995
                                                unbindTouchMove();
1996
                                                if(pointerMoved || numPointers > 1) {
1997
                                                        return;
1998
                                                }
1999
                                                lock = true;
2000
                                                e.preventDefault();
2001
                                                clearTimeout(timeout);
2002
                                                timeout = setTimeout(function() {
2003
                                                        lock = false;
2004
                                                }, ghostClickDelay);
2005
                                                callback();
2006
                                        });
2007
                                });
2008

    
2009
                        }
2010

    
2011
                        elem.on('click' + ns, function() {
2012
                                if(!lock) {
2013
                                        callback();
2014
                                }
2015
                        });
2016
                });
2017
        };
2018

    
2019
        $.fn.destroyMfpFastClick = function() {
2020
                $(this).off('touchstart' + ns + ' click' + ns);
2021
                if(supportsTouch) _window.off('touchmove'+ns+' touchend'+ns);
2022
        };
2023
})();
2024

    
2025
/*>>fastclick*/
2026
})(window.jQuery || window.Zepto);