Dotclear

source: admin/js/jquery/jquery.magnific-popup.js @ 3368:bb25979b0371

Revision 3368:bb25979b0371, 40.7 KB checked in by franck <carnet.franck.paul@…>, 9 years ago (diff)

Replace old jQuery modal js code by the Magnific-Popup responsive jQuery plugin ( http://dimsemenov.com/plugins/magnific-popup/, MIT Licence)

Line 
1/*! Magnific Popup - v1.1.0 - 2016-02-20
2* http://dimsemenov.com/plugins/magnific-popup/
3* Copyright (c) 2016 Dmitry Semenov; */
4;(function (factory) {
5if (typeof define === 'function' && define.amd) {
6 // AMD. Register as an anonymous module.
7 define(['jquery'], factory);
8 } else if (typeof exports === 'object') {
9 // Node/CommonJS
10 factory(require('jquery'));
11 } else {
12 // Browser globals
13 factory(window.jQuery || window.Zepto);
14 }
15 }(function($) {
16
17/*>>core*/
18/**
19 *
20 * Magnific Popup Core JS file
21 *
22 */
23
24
25/**
26 * Private static constants
27 */
28var CLOSE_EVENT = 'Close',
29     BEFORE_CLOSE_EVENT = 'BeforeClose',
30     AFTER_CLOSE_EVENT = 'AfterClose',
31     BEFORE_APPEND_EVENT = 'BeforeAppend',
32     MARKUP_PARSE_EVENT = 'MarkupParse',
33     OPEN_EVENT = 'Open',
34     CHANGE_EVENT = 'Change',
35     NS = 'mfp',
36     EVENT_NS = '.' + NS,
37     READY_CLASS = 'mfp-ready',
38     REMOVING_CLASS = 'mfp-removing',
39     PREVENT_CLOSE_CLASS = 'mfp-prevent-close';
40
41
42/**
43 * Private vars
44 */
45/*jshint -W079 */
46var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this'
47     MagnificPopup = function(){},
48     _isJQ = !!(window.jQuery),
49     _prevStatus,
50     _window = $(window),
51     _document,
52     _prevContentType,
53     _wrapClasses,
54     _currPopupType;
55
56
57/**
58 * Private functions
59 */
60var _mfpOn = function(name, f) {
61          mfp.ev.on(NS + name + EVENT_NS, f);
62     },
63     _getEl = function(className, appendTo, html, raw) {
64          var el = document.createElement('div');
65          el.className = 'mfp-'+className;
66          if(html) {
67               el.innerHTML = html;
68          }
69          if(!raw) {
70               el = $(el);
71               if(appendTo) {
72                    el.appendTo(appendTo);
73               }
74          } else if(appendTo) {
75               appendTo.appendChild(el);
76          }
77          return el;
78     },
79     _mfpTrigger = function(e, data) {
80          mfp.ev.triggerHandler(NS + e, data);
81
82          if(mfp.st.callbacks) {
83               // converts "mfpEventName" to "eventName" callback and triggers it if it's present
84               e = e.charAt(0).toLowerCase() + e.slice(1);
85               if(mfp.st.callbacks[e]) {
86                    mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
87               }
88          }
89     },
90     _getCloseBtn = function(type) {
91          if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
92               mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
93               _currPopupType = type;
94          }
95          return mfp.currTemplate.closeBtn;
96     },
97     // Initialize Magnific Popup only when called at least once
98     _checkInstance = function() {
99          if(!$.magnificPopup.instance) {
100               /*jshint -W020 */
101               mfp = new MagnificPopup();
102               mfp.init();
103               $.magnificPopup.instance = mfp;
104          }
105     },
106     // CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
107     supportsTransitions = function() {
108          var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
109               v = ['ms','O','Moz','Webkit']; // 'v' for vendor
110
111          if( s['transition'] !== undefined ) {
112               return true;
113          }
114
115          while( v.length ) {
116               if( v.pop() + 'Transition' in s ) {
117                    return true;
118               }
119          }
120
121          return false;
122     };
123
124
125
126/**
127 * Public functions
128 */
129MagnificPopup.prototype = {
130
131     constructor: MagnificPopup,
132
133     /**
134      * Initializes Magnific Popup plugin.
135      * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
136      */
137     init: function() {
138          var appVersion = navigator.appVersion;
139          mfp.isLowIE = mfp.isIE8 = document.all && !document.addEventListener;
140          mfp.isAndroid = (/android/gi).test(appVersion);
141          mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
142          mfp.supportsTransition = supportsTransitions();
143
144          // We disable fixed positioned lightbox on devices that don't handle it nicely.
145          // If you know a better way of detecting this - let me know.
146          mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
147          _document = $(document);
148
149          mfp.popupsCache = {};
150     },
151
152     /**
153      * Opens popup
154      * @param  data [description]
155      */
156     open: function(data) {
157
158          var i;
159
160          if(data.isObj === false) {
161               // convert jQuery collection to array to avoid conflicts later
162               mfp.items = data.items.toArray();
163
164               mfp.index = 0;
165               var items = data.items,
166                    item;
167               for(i = 0; i < items.length; i++) {
168                    item = items[i];
169                    if(item.parsed) {
170                         item = item.el[0];
171                    }
172                    if(item === data.el[0]) {
173                         mfp.index = i;
174                         break;
175                    }
176               }
177          } else {
178               mfp.items = $.isArray(data.items) ? data.items : [data.items];
179               mfp.index = data.index || 0;
180          }
181
182          // if popup is already opened - we just update the content
183          if(mfp.isOpen) {
184               mfp.updateItemHTML();
185               return;
186          }
187
188          mfp.types = [];
189          _wrapClasses = '';
190          if(data.mainEl && data.mainEl.length) {
191               mfp.ev = data.mainEl.eq(0);
192          } else {
193               mfp.ev = _document;
194          }
195
196          if(data.key) {
197               if(!mfp.popupsCache[data.key]) {
198                    mfp.popupsCache[data.key] = {};
199               }
200               mfp.currTemplate = mfp.popupsCache[data.key];
201          } else {
202               mfp.currTemplate = {};
203          }
204
205
206
207          mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data );
208          mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;
209
210          if(mfp.st.modal) {
211               mfp.st.closeOnContentClick = false;
212               mfp.st.closeOnBgClick = false;
213               mfp.st.showCloseBtn = false;
214               mfp.st.enableEscapeKey = false;
215          }
216
217
218          // Building markup
219          // main containers are created only once
220          if(!mfp.bgOverlay) {
221
222               // Dark overlay
223               mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() {
224                    mfp.close();
225               });
226
227               mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) {
228                    if(mfp._checkIfClose(e.target)) {
229                         mfp.close();
230                    }
231               });
232
233               mfp.container = _getEl('container', mfp.wrap);
234          }
235
236          mfp.contentContainer = _getEl('content');
237          if(mfp.st.preloader) {
238               mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading);
239          }
240
241
242          // Initializing modules
243          var modules = $.magnificPopup.modules;
244          for(i = 0; i < modules.length; i++) {
245               var n = modules[i];
246               n = n.charAt(0).toUpperCase() + n.slice(1);
247               mfp['init'+n].call(mfp);
248          }
249          _mfpTrigger('BeforeOpen');
250
251
252          if(mfp.st.showCloseBtn) {
253               // Close button
254               if(!mfp.st.closeBtnInside) {
255                    mfp.wrap.append( _getCloseBtn() );
256               } else {
257                    _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
258                         values.close_replaceWith = _getCloseBtn(item.type);
259                    });
260                    _wrapClasses += ' mfp-close-btn-in';
261               }
262          }
263
264          if(mfp.st.alignTop) {
265               _wrapClasses += ' mfp-align-top';
266          }
267
268
269
270          if(mfp.fixedContentPos) {
271               mfp.wrap.css({
272                    overflow: mfp.st.overflowY,
273                    overflowX: 'hidden',
274                    overflowY: mfp.st.overflowY
275               });
276          } else {
277               mfp.wrap.css({
278                    top: _window.scrollTop(),
279                    position: 'absolute'
280               });
281          }
282          if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) {
283               mfp.bgOverlay.css({
284                    height: _document.height(),
285                    position: 'absolute'
286               });
287          }
288
289
290
291          if(mfp.st.enableEscapeKey) {
292               // Close on ESC key
293               _document.on('keyup' + EVENT_NS, function(e) {
294                    if(e.keyCode === 27) {
295                         mfp.close();
296                    }
297               });
298          }
299
300          _window.on('resize' + EVENT_NS, function() {
301               mfp.updateSize();
302          });
303
304
305          if(!mfp.st.closeOnContentClick) {
306               _wrapClasses += ' mfp-auto-cursor';
307          }
308
309          if(_wrapClasses)
310               mfp.wrap.addClass(_wrapClasses);
311
312
313          // this triggers recalculation of layout, so we get it once to not to trigger twice
314          var windowHeight = mfp.wH = _window.height();
315
316
317          var windowStyles = {};
318
319          if( mfp.fixedContentPos ) {
320            if(mfp._hasScrollBar(windowHeight)){
321                var s = mfp._getScrollbarSize();
322                if(s) {
323                    windowStyles.marginRight = s;
324                }
325            }
326        }
327
328          if(mfp.fixedContentPos) {
329               if(!mfp.isIE7) {
330                    windowStyles.overflow = 'hidden';
331               } else {
332                    // ie7 double-scroll bug
333                    $('body, html').css('overflow', 'hidden');
334               }
335          }
336
337
338
339          var classesToadd = mfp.st.mainClass;
340          if(mfp.isIE7) {
341               classesToadd += ' mfp-ie7';
342          }
343          if(classesToadd) {
344               mfp._addClassToMFP( classesToadd );
345          }
346
347          // add content
348          mfp.updateItemHTML();
349
350          _mfpTrigger('BuildControls');
351
352          // remove scrollbar, add margin e.t.c
353          $('html').css(windowStyles);
354
355          // add everything to DOM
356          mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || $(document.body) );
357
358          // Save last focused element
359          mfp._lastFocusedEl = document.activeElement;
360
361          // Wait for next cycle to allow CSS transition
362          setTimeout(function() {
363
364               if(mfp.content) {
365                    mfp._addClassToMFP(READY_CLASS);
366                    mfp._setFocus();
367               } else {
368                    // if content is not defined (not loaded e.t.c) we add class only for BG
369                    mfp.bgOverlay.addClass(READY_CLASS);
370               }
371
372               // Trap the focus in popup
373               _document.on('focusin' + EVENT_NS, mfp._onFocusIn);
374
375          }, 16);
376
377          mfp.isOpen = true;
378          mfp.updateSize(windowHeight);
379          _mfpTrigger(OPEN_EVENT);
380
381          return data;
382     },
383
384     /**
385      * Closes the popup
386      */
387     close: function() {
388          if(!mfp.isOpen) return;
389          _mfpTrigger(BEFORE_CLOSE_EVENT);
390
391          mfp.isOpen = false;
392          // for CSS3 animation
393          if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition )  {
394               mfp._addClassToMFP(REMOVING_CLASS);
395               setTimeout(function() {
396                    mfp._close();
397               }, mfp.st.removalDelay);
398          } else {
399               mfp._close();
400          }
401     },
402
403     /**
404      * Helper for close() function
405      */
406     _close: function() {
407          _mfpTrigger(CLOSE_EVENT);
408
409          var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' ';
410
411          mfp.bgOverlay.detach();
412          mfp.wrap.detach();
413          mfp.container.empty();
414
415          if(mfp.st.mainClass) {
416               classesToRemove += mfp.st.mainClass + ' ';
417          }
418
419          mfp._removeClassFromMFP(classesToRemove);
420
421          if(mfp.fixedContentPos) {
422               var windowStyles = {marginRight: ''};
423               if(mfp.isIE7) {
424                    $('body, html').css('overflow', '');
425               } else {
426                    windowStyles.overflow = '';
427               }
428               $('html').css(windowStyles);
429          }
430
431          _document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS);
432          mfp.ev.off(EVENT_NS);
433
434          // clean up DOM elements that aren't removed
435          mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style');
436          mfp.bgOverlay.attr('class', 'mfp-bg');
437          mfp.container.attr('class', 'mfp-container');
438
439          // remove close button from target element
440          if(mfp.st.showCloseBtn &&
441          (!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) {
442               if(mfp.currTemplate.closeBtn)
443                    mfp.currTemplate.closeBtn.detach();
444          }
445
446
447          if(mfp.st.autoFocusLast && mfp._lastFocusedEl) {
448               $(mfp._lastFocusedEl).focus(); // put tab focus back
449          }
450          mfp.currItem = null;
451          mfp.content = null;
452          mfp.currTemplate = null;
453          mfp.prevHeight = 0;
454
455          _mfpTrigger(AFTER_CLOSE_EVENT);
456     },
457
458     updateSize: function(winHeight) {
459
460          if(mfp.isIOS) {
461               // fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2
462               var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
463               var height = window.innerHeight * zoomLevel;
464               mfp.wrap.css('height', height);
465               mfp.wH = height;
466          } else {
467               mfp.wH = winHeight || _window.height();
468          }
469          // Fixes #84: popup incorrectly positioned with position:relative on body
470          if(!mfp.fixedContentPos) {
471               mfp.wrap.css('height', mfp.wH);
472          }
473
474          _mfpTrigger('Resize');
475
476     },
477
478     /**
479      * Set content of popup based on current index
480      */
481     updateItemHTML: function() {
482          var item = mfp.items[mfp.index];
483
484          // Detach and perform modifications
485          mfp.contentContainer.detach();
486
487          if(mfp.content)
488               mfp.content.detach();
489
490          if(!item.parsed) {
491               item = mfp.parseEl( mfp.index );
492          }
493
494          var type = item.type;
495
496          _mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]);
497          // BeforeChange event works like so:
498          // _mfpOn('BeforeChange', function(e, prevType, newType) { });
499
500          mfp.currItem = item;
501
502          if(!mfp.currTemplate[type]) {
503               var markup = mfp.st[type] ? mfp.st[type].markup : false;
504
505               // allows to modify markup
506               _mfpTrigger('FirstMarkupParse', markup);
507
508               if(markup) {
509                    mfp.currTemplate[type] = $(markup);
510               } else {
511                    // if there is no markup found we just define that template is parsed
512                    mfp.currTemplate[type] = true;
513               }
514          }
515
516          if(_prevContentType && _prevContentType !== item.type) {
517               mfp.container.removeClass('mfp-'+_prevContentType+'-holder');
518          }
519
520          var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]);
521          mfp.appendContent(newContent, type);
522
523          item.preloaded = true;
524
525          _mfpTrigger(CHANGE_EVENT, item);
526          _prevContentType = item.type;
527
528          // Append container back after its content changed
529          mfp.container.prepend(mfp.contentContainer);
530
531          _mfpTrigger('AfterChange');
532     },
533
534
535     /**
536      * Set HTML content of popup
537      */
538     appendContent: function(newContent, type) {
539          mfp.content = newContent;
540
541          if(newContent) {
542               if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
543                    mfp.currTemplate[type] === true) {
544                    // if there is no markup, we just append close button element inside
545                    if(!mfp.content.find('.mfp-close').length) {
546                         mfp.content.append(_getCloseBtn());
547                    }
548               } else {
549                    mfp.content = newContent;
550               }
551          } else {
552               mfp.content = '';
553          }
554
555          _mfpTrigger(BEFORE_APPEND_EVENT);
556          mfp.container.addClass('mfp-'+type+'-holder');
557
558          mfp.contentContainer.append(mfp.content);
559     },
560
561
562     /**
563      * Creates Magnific Popup data object based on given data
564      * @param  {int} index Index of item to parse
565      */
566     parseEl: function(index) {
567          var item = mfp.items[index],
568               type;
569
570          if(item.tagName) {
571               item = { el: $(item) };
572          } else {
573               type = item.type;
574               item = { data: item, src: item.src };
575          }
576
577          if(item.el) {
578               var types = mfp.types;
579
580               // check for 'mfp-TYPE' class
581               for(var i = 0; i < types.length; i++) {
582                    if( item.el.hasClass('mfp-'+types[i]) ) {
583                         type = types[i];
584                         break;
585                    }
586               }
587
588               item.src = item.el.attr('data-mfp-src');
589               if(!item.src) {
590                    item.src = item.el.attr('href');
591               }
592          }
593
594          item.type = type || mfp.st.type || 'inline';
595          item.index = index;
596          item.parsed = true;
597          mfp.items[index] = item;
598          _mfpTrigger('ElementParse', item);
599
600          return mfp.items[index];
601     },
602
603
604     /**
605      * Initializes single popup or a group of popups
606      */
607     addGroup: function(el, options) {
608          var eHandler = function(e) {
609               e.mfpEl = this;
610               mfp._openClick(e, el, options);
611          };
612
613          if(!options) {
614               options = {};
615          }
616
617          var eName = 'click.magnificPopup';
618          options.mainEl = el;
619
620          if(options.items) {
621               options.isObj = true;
622               el.off(eName).on(eName, eHandler);
623          } else {
624               options.isObj = false;
625               if(options.delegate) {
626                    el.off(eName).on(eName, options.delegate , eHandler);
627               } else {
628                    options.items = el;
629                    el.off(eName).on(eName, eHandler);
630               }
631          }
632     },
633     _openClick: function(e, el, options) {
634          var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick;
635
636
637          if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey ) ) {
638               return;
639          }
640
641          var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;
642
643          if(disableOn) {
644               if($.isFunction(disableOn)) {
645                    if( !disableOn.call(mfp) ) {
646                         return true;
647                    }
648               } else { // else it's number
649                    if( _window.width() < disableOn ) {
650                         return true;
651                    }
652               }
653          }
654
655          if(e.type) {
656               e.preventDefault();
657
658               // This will prevent popup from closing if element is inside and popup is already opened
659               if(mfp.isOpen) {
660                    e.stopPropagation();
661               }
662          }
663
664          options.el = $(e.mfpEl);
665          if(options.delegate) {
666               options.items = el.find(options.delegate);
667          }
668          mfp.open(options);
669     },
670
671
672     /**
673      * Updates text on preloader
674      */
675     updateStatus: function(status, text) {
676
677          if(mfp.preloader) {
678               if(_prevStatus !== status) {
679                    mfp.container.removeClass('mfp-s-'+_prevStatus);
680               }
681
682               if(!text && status === 'loading') {
683                    text = mfp.st.tLoading;
684               }
685
686               var data = {
687                    status: status,
688                    text: text
689               };
690               // allows to modify status
691               _mfpTrigger('UpdateStatus', data);
692
693               status = data.status;
694               text = data.text;
695
696               mfp.preloader.html(text);
697
698               mfp.preloader.find('a').on('click', function(e) {
699                    e.stopImmediatePropagation();
700               });
701
702               mfp.container.addClass('mfp-s-'+status);
703               _prevStatus = status;
704          }
705     },
706
707
708     /*
709          "Private" helpers that aren't private at all
710      */
711     // Check to close popup or not
712     // "target" is an element that was clicked
713     _checkIfClose: function(target) {
714
715          if($(target).hasClass(PREVENT_CLOSE_CLASS)) {
716               return;
717          }
718
719          var closeOnContent = mfp.st.closeOnContentClick;
720          var closeOnBg = mfp.st.closeOnBgClick;
721
722          if(closeOnContent && closeOnBg) {
723               return true;
724          } else {
725
726               // We close the popup if click is on close button or on preloader. Or if there is no content.
727               if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) {
728                    return true;
729               }
730
731               // if click is outside the content
732               if(  (target !== mfp.content[0] && !$.contains(mfp.content[0], target))  ) {
733                    if(closeOnBg) {
734                         // last check, if the clicked element is in DOM, (in case it's removed onclick)
735                         if( $.contains(document, target) ) {
736                              return true;
737                         }
738                    }
739               } else if(closeOnContent) {
740                    return true;
741               }
742
743          }
744          return false;
745     },
746     _addClassToMFP: function(cName) {
747          mfp.bgOverlay.addClass(cName);
748          mfp.wrap.addClass(cName);
749     },
750     _removeClassFromMFP: function(cName) {
751          this.bgOverlay.removeClass(cName);
752          mfp.wrap.removeClass(cName);
753     },
754     _hasScrollBar: function(winHeight) {
755          return (  (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) );
756     },
757     _setFocus: function() {
758          (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
759     },
760     _onFocusIn: function(e) {
761          if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) {
762               mfp._setFocus();
763               return false;
764          }
765     },
766     _parseMarkup: function(template, values, item) {
767          var arr;
768          if(item.data) {
769               values = $.extend(item.data, values);
770          }
771          _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] );
772
773          $.each(values, function(key, value) {
774               if(value === undefined || value === false) {
775                    return true;
776               }
777               arr = key.split('_');
778               if(arr.length > 1) {
779                    var el = template.find(EVENT_NS + '-'+arr[0]);
780
781                    if(el.length > 0) {
782                         var attr = arr[1];
783                         if(attr === 'replaceWith') {
784                              if(el[0] !== value[0]) {
785                                   el.replaceWith(value);
786                              }
787                         } else if(attr === 'img') {
788                              if(el.is('img')) {
789                                   el.attr('src', value);
790                              } else {
791                                   el.replaceWith( $('<img>').attr('src', value).attr('class', el.attr('class')) );
792                              }
793                         } else {
794                              el.attr(arr[1], value);
795                         }
796                    }
797
798               } else {
799                    template.find(EVENT_NS + '-'+key).html(value);
800               }
801          });
802     },
803
804     _getScrollbarSize: function() {
805          // thx David
806          if(mfp.scrollbarSize === undefined) {
807               var scrollDiv = document.createElement("div");
808               scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
809               document.body.appendChild(scrollDiv);
810               mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
811               document.body.removeChild(scrollDiv);
812          }
813          return mfp.scrollbarSize;
814     }
815
816}; /* MagnificPopup core prototype end */
817
818
819
820
821/**
822 * Public static functions
823 */
824$.magnificPopup = {
825     instance: null,
826     proto: MagnificPopup.prototype,
827     modules: [],
828
829     open: function(options, index) {
830          _checkInstance();
831
832          if(!options) {
833               options = {};
834          } else {
835               options = $.extend(true, {}, options);
836          }
837
838          options.isObj = true;
839          options.index = index || 0;
840          return this.instance.open(options);
841     },
842
843     close: function() {
844          return $.magnificPopup.instance && $.magnificPopup.instance.close();
845     },
846
847     registerModule: function(name, module) {
848          if(module.options) {
849               $.magnificPopup.defaults[name] = module.options;
850          }
851          $.extend(this.proto, module.proto);
852          this.modules.push(name);
853     },
854
855     defaults: {
856
857          // Info about options is in docs:
858          // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options
859
860          disableOn: 0,
861
862          key: null,
863
864          midClick: false,
865
866          mainClass: '',
867
868          preloader: true,
869
870          focus: '', // CSS selector of input to focus after popup is opened
871
872          closeOnContentClick: false,
873
874          closeOnBgClick: true,
875
876          closeBtnInside: true,
877
878          showCloseBtn: true,
879
880          enableEscapeKey: true,
881
882          modal: false,
883
884          alignTop: false,
885
886          removalDelay: 0,
887
888          prependTo: null,
889
890          fixedContentPos: 'auto',
891
892          fixedBgPos: 'auto',
893
894          overflowY: 'auto',
895
896          closeMarkup: '<button title="%title%" type="button" class="mfp-close">&#215;</button>',
897
898          tClose: 'Close (Esc)',
899
900          tLoading: 'Loading...',
901
902          autoFocusLast: true
903
904     }
905};
906
907
908
909$.fn.magnificPopup = function(options) {
910     _checkInstance();
911
912     var jqEl = $(this);
913
914     // We call some API method of first param is a string
915     if (typeof options === "string" ) {
916
917          if(options === 'open') {
918               var items,
919                    itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup,
920                    index = parseInt(arguments[1], 10) || 0;
921
922               if(itemOpts.items) {
923                    items = itemOpts.items[index];
924               } else {
925                    items = jqEl;
926                    if(itemOpts.delegate) {
927                         items = items.find(itemOpts.delegate);
928                    }
929                    items = items.eq( index );
930               }
931               mfp._openClick({mfpEl:items}, jqEl, itemOpts);
932          } else {
933               if(mfp.isOpen)
934                    mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
935          }
936
937     } else {
938          // clone options obj
939          options = $.extend(true, {}, options);
940
941          /*
942           * As Zepto doesn't support .data() method for objects
943           * and it works only in normal browsers
944           * we assign "options" object directly to the DOM element. FTW!
945           */
946          if(_isJQ) {
947               jqEl.data('magnificPopup', options);
948          } else {
949               jqEl[0].magnificPopup = options;
950          }
951
952          mfp.addGroup(jqEl, options);
953
954     }
955     return jqEl;
956};
957
958/*>>core*/
959
960/*>>inline*/
961
962var INLINE_NS = 'inline',
963     _hiddenClass,
964     _inlinePlaceholder,
965     _lastInlineElement,
966     _putInlineElementsBack = function() {
967          if(_lastInlineElement) {
968               _inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach();
969               _lastInlineElement = null;
970          }
971     };
972
973$.magnificPopup.registerModule(INLINE_NS, {
974     options: {
975          hiddenClass: 'hide', // will be appended with `mfp-` prefix
976          markup: '',
977          tNotFound: 'Content not found'
978     },
979     proto: {
980
981          initInline: function() {
982               mfp.types.push(INLINE_NS);
983
984               _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() {
985                    _putInlineElementsBack();
986               });
987          },
988
989          getInline: function(item, template) {
990
991               _putInlineElementsBack();
992
993               if(item.src) {
994                    var inlineSt = mfp.st.inline,
995                         el = $(item.src);
996
997                    if(el.length) {
998
999                         // If target element has parent - we replace it with placeholder and put it back after popup is closed
1000                         var parent = el[0].parentNode;
1001                         if(parent && parent.tagName) {
1002                              if(!_inlinePlaceholder) {
1003                                   _hiddenClass = inlineSt.hiddenClass;
1004                                   _inlinePlaceholder = _getEl(_hiddenClass);
1005                                   _hiddenClass = 'mfp-'+_hiddenClass;
1006                              }
1007                              // replace target inline element with placeholder
1008                              _lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass);
1009                         }
1010
1011                         mfp.updateStatus('ready');
1012                    } else {
1013                         mfp.updateStatus('error', inlineSt.tNotFound);
1014                         el = $('<div>');
1015                    }
1016
1017                    item.inlineElement = el;
1018                    return el;
1019               }
1020
1021               mfp.updateStatus('ready');
1022               mfp._parseMarkup(template, {}, item);
1023               return template;
1024          }
1025     }
1026});
1027
1028/*>>inline*/
1029
1030/*>>ajax*/
1031var AJAX_NS = 'ajax',
1032     _ajaxCur,
1033     _removeAjaxCursor = function() {
1034          if(_ajaxCur) {
1035               $(document.body).removeClass(_ajaxCur);
1036          }
1037     },
1038     _destroyAjaxRequest = function() {
1039          _removeAjaxCursor();
1040          if(mfp.req) {
1041               mfp.req.abort();
1042          }
1043     };
1044
1045$.magnificPopup.registerModule(AJAX_NS, {
1046
1047     options: {
1048          settings: null,
1049          cursor: 'mfp-ajax-cur',
1050          tError: '<a href="%url%">The content</a> could not be loaded.'
1051     },
1052
1053     proto: {
1054          initAjax: function() {
1055               mfp.types.push(AJAX_NS);
1056               _ajaxCur = mfp.st.ajax.cursor;
1057
1058               _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest);
1059               _mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest);
1060          },
1061          getAjax: function(item) {
1062
1063               if(_ajaxCur) {
1064                    $(document.body).addClass(_ajaxCur);
1065               }
1066
1067               mfp.updateStatus('loading');
1068
1069               var opts = $.extend({
1070                    url: item.src,
1071                    success: function(data, textStatus, jqXHR) {
1072                         var temp = {
1073                              data:data,
1074                              xhr:jqXHR
1075                         };
1076
1077                         _mfpTrigger('ParseAjax', temp);
1078
1079                         mfp.appendContent( $(temp.data), AJAX_NS );
1080
1081                         item.finished = true;
1082
1083                         _removeAjaxCursor();
1084
1085                         mfp._setFocus();
1086
1087                         setTimeout(function() {
1088                              mfp.wrap.addClass(READY_CLASS);
1089                         }, 16);
1090
1091                         mfp.updateStatus('ready');
1092
1093                         _mfpTrigger('AjaxContentAdded');
1094                    },
1095                    error: function() {
1096                         _removeAjaxCursor();
1097                         item.finished = item.loadError = true;
1098                         mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src));
1099                    }
1100               }, mfp.st.ajax.settings);
1101
1102               mfp.req = $.ajax(opts);
1103
1104               return '';
1105          }
1106     }
1107});
1108
1109/*>>ajax*/
1110
1111/*>>image*/
1112var _imgInterval,
1113     _getTitle = function(item) {
1114          if(item.data && item.data.title !== undefined)
1115               return item.data.title;
1116
1117          var src = mfp.st.image.titleSrc;
1118
1119          if(src) {
1120               if($.isFunction(src)) {
1121                    return src.call(mfp, item);
1122               } else if(item.el) {
1123                    return item.el.attr(src) || '';
1124               }
1125          }
1126          return '';
1127     };
1128
1129$.magnificPopup.registerModule('image', {
1130
1131     options: {
1132          markup: '<div class="mfp-figure">'+
1133                         '<div class="mfp-close"></div>'+
1134                         '<figure>'+
1135                              '<div class="mfp-img"></div>'+
1136                              '<figcaption>'+
1137                                   '<div class="mfp-bottom-bar">'+
1138                                        '<div class="mfp-title"></div>'+
1139                                        '<div class="mfp-counter"></div>'+
1140                                   '</div>'+
1141                              '</figcaption>'+
1142                         '</figure>'+
1143                    '</div>',
1144          cursor: 'mfp-zoom-out-cur',
1145          titleSrc: 'title',
1146          verticalFit: true,
1147          tError: '<a href="%url%">The image</a> could not be loaded.'
1148     },
1149
1150     proto: {
1151          initImage: function() {
1152               var imgSt = mfp.st.image,
1153                    ns = '.image';
1154
1155               mfp.types.push('image');
1156
1157               _mfpOn(OPEN_EVENT+ns, function() {
1158                    if(mfp.currItem.type === 'image' && imgSt.cursor) {
1159                         $(document.body).addClass(imgSt.cursor);
1160                    }
1161               });
1162
1163               _mfpOn(CLOSE_EVENT+ns, function() {
1164                    if(imgSt.cursor) {
1165                         $(document.body).removeClass(imgSt.cursor);
1166                    }
1167                    _window.off('resize' + EVENT_NS);
1168               });
1169
1170               _mfpOn('Resize'+ns, mfp.resizeImage);
1171               if(mfp.isLowIE) {
1172                    _mfpOn('AfterChange', mfp.resizeImage);
1173               }
1174          },
1175          resizeImage: function() {
1176               var item = mfp.currItem;
1177               if(!item || !item.img) return;
1178
1179               if(mfp.st.image.verticalFit) {
1180                    var decr = 0;
1181                    // fix box-sizing in ie7/8
1182                    if(mfp.isLowIE) {
1183                         decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10);
1184                    }
1185                    item.img.css('max-height', mfp.wH-decr);
1186               }
1187          },
1188          _onImageHasSize: function(item) {
1189               if(item.img) {
1190
1191                    item.hasSize = true;
1192
1193                    if(_imgInterval) {
1194                         clearInterval(_imgInterval);
1195                    }
1196
1197                    item.isCheckingImgSize = false;
1198
1199                    _mfpTrigger('ImageHasSize', item);
1200
1201                    if(item.imgHidden) {
1202                         if(mfp.content)
1203                              mfp.content.removeClass('mfp-loading');
1204
1205                         item.imgHidden = false;
1206                    }
1207
1208               }
1209          },
1210
1211          /**
1212           * Function that loops until the image has size to display elements that rely on it asap
1213           */
1214          findImageSize: function(item) {
1215
1216               var counter = 0,
1217                    img = item.img[0],
1218                    mfpSetInterval = function(delay) {
1219
1220                         if(_imgInterval) {
1221                              clearInterval(_imgInterval);
1222                         }
1223                         // decelerating interval that checks for size of an image
1224                         _imgInterval = setInterval(function() {
1225                              if(img.naturalWidth > 0) {
1226                                   mfp._onImageHasSize(item);
1227                                   return;
1228                              }
1229
1230                              if(counter > 200) {
1231                                   clearInterval(_imgInterval);
1232                              }
1233
1234                              counter++;
1235                              if(counter === 3) {
1236                                   mfpSetInterval(10);
1237                              } else if(counter === 40) {
1238                                   mfpSetInterval(50);
1239                              } else if(counter === 100) {
1240                                   mfpSetInterval(500);
1241                              }
1242                         }, delay);
1243                    };
1244
1245               mfpSetInterval(1);
1246          },
1247
1248          getImage: function(item, template) {
1249
1250               var guard = 0,
1251
1252                    // image load complete handler
1253                    onLoadComplete = function() {
1254                         if(item) {
1255                              if (item.img[0].complete) {
1256                                   item.img.off('.mfploader');
1257
1258                                   if(item === mfp.currItem){
1259                                        mfp._onImageHasSize(item);
1260
1261                                        mfp.updateStatus('ready');
1262                                   }
1263
1264                                   item.hasSize = true;
1265                                   item.loaded = true;
1266
1267                                   _mfpTrigger('ImageLoadComplete');
1268
1269                              }
1270                              else {
1271                                   // if image complete check fails 200 times (20 sec), we assume that there was an error.
1272                                   guard++;
1273                                   if(guard < 200) {
1274                                        setTimeout(onLoadComplete,100);
1275                                   } else {
1276                                        onLoadError();
1277                                   }
1278                              }
1279                         }
1280                    },
1281
1282                    // image error handler
1283                    onLoadError = function() {
1284                         if(item) {
1285                              item.img.off('.mfploader');
1286                              if(item === mfp.currItem){
1287                                   mfp._onImageHasSize(item);
1288                                   mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
1289                              }
1290
1291                              item.hasSize = true;
1292                              item.loaded = true;
1293                              item.loadError = true;
1294                         }
1295                    },
1296                    imgSt = mfp.st.image;
1297
1298
1299               var el = template.find('.mfp-img');
1300               if(el.length) {
1301                    var img = document.createElement('img');
1302                    img.className = 'mfp-img';
1303                    if(item.el && item.el.find('img').length) {
1304                         img.alt = item.el.find('img').attr('alt');
1305                    }
1306                    item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError);
1307                    img.src = item.src;
1308
1309                    // without clone() "error" event is not firing when IMG is replaced by new IMG
1310                    // TODO: find a way to avoid such cloning
1311                    if(el.is('img')) {
1312                         item.img = item.img.clone();
1313                    }
1314
1315                    img = item.img[0];
1316                    if(img.naturalWidth > 0) {
1317                         item.hasSize = true;
1318                    } else if(!img.width) {
1319                         item.hasSize = false;
1320                    }
1321               }
1322
1323               mfp._parseMarkup(template, {
1324                    title: _getTitle(item),
1325                    img_replaceWith: item.img
1326               }, item);
1327
1328               mfp.resizeImage();
1329
1330               if(item.hasSize) {
1331                    if(_imgInterval) clearInterval(_imgInterval);
1332
1333                    if(item.loadError) {
1334                         template.addClass('mfp-loading');
1335                         mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
1336                    } else {
1337                         template.removeClass('mfp-loading');
1338                         mfp.updateStatus('ready');
1339                    }
1340                    return template;
1341               }
1342
1343               mfp.updateStatus('loading');
1344               item.loading = true;
1345
1346               if(!item.hasSize) {
1347                    item.imgHidden = true;
1348                    template.addClass('mfp-loading');
1349                    mfp.findImageSize(item);
1350               }
1351
1352               return template;
1353          }
1354     }
1355});
1356
1357/*>>image*/
1358
1359/*>>zoom*/
1360var hasMozTransform,
1361     getHasMozTransform = function() {
1362          if(hasMozTransform === undefined) {
1363               hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
1364          }
1365          return hasMozTransform;
1366     };
1367
1368$.magnificPopup.registerModule('zoom', {
1369
1370     options: {
1371          enabled: false,
1372          easing: 'ease-in-out',
1373          duration: 300,
1374          opener: function(element) {
1375               return element.is('img') ? element : element.find('img');
1376          }
1377     },
1378
1379     proto: {
1380
1381          initZoom: function() {
1382               var zoomSt = mfp.st.zoom,
1383                    ns = '.zoom',
1384                    image;
1385
1386               if(!zoomSt.enabled || !mfp.supportsTransition) {
1387                    return;
1388               }
1389
1390               var duration = zoomSt.duration,
1391                    getElToAnimate = function(image) {
1392                         var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
1393                              transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
1394                              cssObj = {
1395                                   position: 'fixed',
1396                                   zIndex: 9999,
1397                                   left: 0,
1398                                   top: 0,
1399                                   '-webkit-backface-visibility': 'hidden'
1400                              },
1401                              t = 'transition';
1402
1403                         cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;
1404
1405                         newImg.css(cssObj);
1406                         return newImg;
1407                    },
1408                    showMainContent = function() {
1409                         mfp.content.css('visibility', 'visible');
1410                    },
1411                    openTimeout,
1412                    animatedImg;
1413
1414               _mfpOn('BuildControls'+ns, function() {
1415                    if(mfp._allowZoom()) {
1416
1417                         clearTimeout(openTimeout);
1418                         mfp.content.css('visibility', 'hidden');
1419
1420                         // Basically, all code below does is clones existing image, puts in on top of the current one and animated it
1421
1422                         image = mfp._getItemToZoom();
1423
1424                         if(!image) {
1425                              showMainContent();
1426                              return;
1427                         }
1428
1429                         animatedImg = getElToAnimate(image);
1430
1431                         animatedImg.css( mfp._getOffset() );
1432
1433                         mfp.wrap.append(animatedImg);
1434
1435                         openTimeout = setTimeout(function() {
1436                              animatedImg.css( mfp._getOffset( true ) );
1437                              openTimeout = setTimeout(function() {
1438
1439                                   showMainContent();
1440
1441                                   setTimeout(function() {
1442                                        animatedImg.remove();
1443                                        image = animatedImg = null;
1444                                        _mfpTrigger('ZoomAnimationEnded');
1445                                   }, 16); // avoid blink when switching images
1446
1447                              }, duration); // this timeout equals animation duration
1448
1449                         }, 16); // by adding this timeout we avoid short glitch at the beginning of animation
1450
1451
1452                         // Lots of timeouts...
1453                    }
1454               });
1455               _mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
1456                    if(mfp._allowZoom()) {
1457
1458                         clearTimeout(openTimeout);
1459
1460                         mfp.st.removalDelay = duration;
1461
1462                         if(!image) {
1463                              image = mfp._getItemToZoom();
1464                              if(!image) {
1465                                   return;
1466                              }
1467                              animatedImg = getElToAnimate(image);
1468                         }
1469
1470                         animatedImg.css( mfp._getOffset(true) );
1471                         mfp.wrap.append(animatedImg);
1472                         mfp.content.css('visibility', 'hidden');
1473
1474                         setTimeout(function() {
1475                              animatedImg.css( mfp._getOffset() );
1476                         }, 16);
1477                    }
1478
1479               });
1480
1481               _mfpOn(CLOSE_EVENT+ns, function() {
1482                    if(mfp._allowZoom()) {
1483                         showMainContent();
1484                         if(animatedImg) {
1485                              animatedImg.remove();
1486                         }
1487                         image = null;
1488                    }
1489               });
1490          },
1491
1492          _allowZoom: function() {
1493               return mfp.currItem.type === 'image';
1494          },
1495
1496          _getItemToZoom: function() {
1497               if(mfp.currItem.hasSize) {
1498                    return mfp.currItem.img;
1499               } else {
1500                    return false;
1501               }
1502          },
1503
1504          // Get element postion relative to viewport
1505          _getOffset: function(isLarge) {
1506               var el;
1507               if(isLarge) {
1508                    el = mfp.currItem.img;
1509               } else {
1510                    el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
1511               }
1512
1513               var offset = el.offset();
1514               var paddingTop = parseInt(el.css('padding-top'),10);
1515               var paddingBottom = parseInt(el.css('padding-bottom'),10);
1516               offset.top -= ( $(window).scrollTop() - paddingTop );
1517
1518
1519               /*
1520
1521               Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.
1522
1523                */
1524               var obj = {
1525                    width: el.width(),
1526                    // fix Zepto height+padding issue
1527                    height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
1528               };
1529
1530               // I hate to do this, but there is no another option
1531               if( getHasMozTransform() ) {
1532                    obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
1533               } else {
1534                    obj.left = offset.left;
1535                    obj.top = offset.top;
1536               }
1537               return obj;
1538          }
1539
1540     }
1541});
1542
1543
1544
1545/*>>zoom*/
1546
1547/*>>iframe*/
1548
1549var IFRAME_NS = 'iframe',
1550     _emptyPage = '//about:blank',
1551
1552     _fixIframeBugs = function(isShowing) {
1553          if(mfp.currTemplate[IFRAME_NS]) {
1554               var el = mfp.currTemplate[IFRAME_NS].find('iframe');
1555               if(el.length) {
1556                    // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
1557                    if(!isShowing) {
1558                         el[0].src = _emptyPage;
1559                    }
1560
1561                    // IE8 black screen bug fix
1562                    if(mfp.isIE8) {
1563                         el.css('display', isShowing ? 'block' : 'none');
1564                    }
1565               }
1566          }
1567     };
1568
1569$.magnificPopup.registerModule(IFRAME_NS, {
1570
1571     options: {
1572          markup: '<div class="mfp-iframe-scaler">'+
1573                         '<div class="mfp-close"></div>'+
1574                         '<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+
1575                    '</div>',
1576
1577          srcAction: 'iframe_src',
1578
1579          // we don't care and support only one default type of URL by default
1580          patterns: {
1581               youtube: {
1582                    index: 'youtube.com',
1583                    id: 'v=',
1584                    src: '//www.youtube.com/embed/%id%?autoplay=1'
1585               },
1586               vimeo: {
1587                    index: 'vimeo.com/',
1588                    id: '/',
1589                    src: '//player.vimeo.com/video/%id%?autoplay=1'
1590               },
1591               gmaps: {
1592                    index: '//maps.google.',
1593                    src: '%id%&output=embed'
1594               }
1595          }
1596     },
1597
1598     proto: {
1599          initIframe: function() {
1600               mfp.types.push(IFRAME_NS);
1601
1602               _mfpOn('BeforeChange', function(e, prevType, newType) {
1603                    if(prevType !== newType) {
1604                         if(prevType === IFRAME_NS) {
1605                              _fixIframeBugs(); // iframe if removed
1606                         } else if(newType === IFRAME_NS) {
1607                              _fixIframeBugs(true); // iframe is showing
1608                         }
1609                    }// else {
1610                         // iframe source is switched, don't do anything
1611                    //}
1612               });
1613
1614               _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
1615                    _fixIframeBugs();
1616               });
1617          },
1618
1619          getIframe: function(item, template) {
1620               var embedSrc = item.src;
1621               var iframeSt = mfp.st.iframe;
1622
1623               $.each(iframeSt.patterns, function() {
1624                    if(embedSrc.indexOf( this.index ) > -1) {
1625                         if(this.id) {
1626                              if(typeof this.id === 'string') {
1627                                   embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
1628                              } else {
1629                                   embedSrc = this.id.call( this, embedSrc );
1630                              }
1631                         }
1632                         embedSrc = this.src.replace('%id%', embedSrc );
1633                         return false; // break;
1634                    }
1635               });
1636
1637               var dataObj = {};
1638               if(iframeSt.srcAction) {
1639                    dataObj[iframeSt.srcAction] = embedSrc;
1640               }
1641               mfp._parseMarkup(template, dataObj, item);
1642
1643               mfp.updateStatus('ready');
1644
1645               return template;
1646          }
1647     }
1648});
1649
1650
1651
1652/*>>iframe*/
1653
1654/*>>gallery*/
1655/**
1656 * Get looped index depending on number of slides
1657 */
1658var _getLoopedId = function(index) {
1659          var numSlides = mfp.items.length;
1660          if(index > numSlides - 1) {
1661               return index - numSlides;
1662          } else  if(index < 0) {
1663               return numSlides + index;
1664          }
1665          return index;
1666     },
1667     _replaceCurrTotal = function(text, curr, total) {
1668          return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
1669     };
1670
1671$.magnificPopup.registerModule('gallery', {
1672
1673     options: {
1674          enabled: false,
1675          arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
1676          preload: [0,2],
1677          navigateByImgClick: true,
1678          arrows: true,
1679
1680          tPrev: 'Previous (Left arrow key)',
1681          tNext: 'Next (Right arrow key)',
1682          tCounter: '%curr% of %total%'
1683     },
1684
1685     proto: {
1686          initGallery: function() {
1687
1688               var gSt = mfp.st.gallery,
1689                    ns = '.mfp-gallery';
1690
1691               mfp.direction = true; // true - next, false - prev
1692
1693               if(!gSt || !gSt.enabled ) return false;
1694
1695               _wrapClasses += ' mfp-gallery';
1696
1697               _mfpOn(OPEN_EVENT+ns, function() {
1698
1699                    if(gSt.navigateByImgClick) {
1700                         mfp.wrap.on('click'+ns, '.mfp-img', function() {
1701                              if(mfp.items.length > 1) {
1702                                   mfp.next();
1703                                   return false;
1704                              }
1705                         });
1706                    }
1707
1708                    _document.on('keydown'+ns, function(e) {
1709                         if (e.keyCode === 37) {
1710                              mfp.prev();
1711                         } else if (e.keyCode === 39) {
1712                              mfp.next();
1713                         }
1714                    });
1715               });
1716
1717               _mfpOn('UpdateStatus'+ns, function(e, data) {
1718                    if(data.text) {
1719                         data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
1720                    }
1721               });
1722
1723               _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
1724                    var l = mfp.items.length;
1725                    values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
1726               });
1727
1728               _mfpOn('BuildControls' + ns, function() {
1729                    if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
1730                         var markup = gSt.arrowMarkup,
1731                              arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS),
1732                              arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS);
1733
1734                         arrowLeft.click(function() {
1735                              mfp.prev();
1736                         });
1737                         arrowRight.click(function() {
1738                              mfp.next();
1739                         });
1740
1741                         mfp.container.append(arrowLeft.add(arrowRight));
1742                    }
1743               });
1744
1745               _mfpOn(CHANGE_EVENT+ns, function() {
1746                    if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);
1747
1748                    mfp._preloadTimeout = setTimeout(function() {
1749                         mfp.preloadNearbyImages();
1750                         mfp._preloadTimeout = null;
1751                    }, 16);
1752               });
1753
1754
1755               _mfpOn(CLOSE_EVENT+ns, function() {
1756                    _document.off(ns);
1757                    mfp.wrap.off('click'+ns);
1758                    mfp.arrowRight = mfp.arrowLeft = null;
1759               });
1760
1761          },
1762          next: function() {
1763               mfp.direction = true;
1764               mfp.index = _getLoopedId(mfp.index + 1);
1765               mfp.updateItemHTML();
1766          },
1767          prev: function() {
1768               mfp.direction = false;
1769               mfp.index = _getLoopedId(mfp.index - 1);
1770               mfp.updateItemHTML();
1771          },
1772          goTo: function(newIndex) {
1773               mfp.direction = (newIndex >= mfp.index);
1774               mfp.index = newIndex;
1775               mfp.updateItemHTML();
1776          },
1777          preloadNearbyImages: function() {
1778               var p = mfp.st.gallery.preload,
1779                    preloadBefore = Math.min(p[0], mfp.items.length),
1780                    preloadAfter = Math.min(p[1], mfp.items.length),
1781                    i;
1782
1783               for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
1784                    mfp._preloadItem(mfp.index+i);
1785               }
1786               for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
1787                    mfp._preloadItem(mfp.index-i);
1788               }
1789          },
1790          _preloadItem: function(index) {
1791               index = _getLoopedId(index);
1792
1793               if(mfp.items[index].preloaded) {
1794                    return;
1795               }
1796
1797               var item = mfp.items[index];
1798               if(!item.parsed) {
1799                    item = mfp.parseEl( index );
1800               }
1801
1802               _mfpTrigger('LazyLoad', item);
1803
1804               if(item.type === 'image') {
1805                    item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
1806                         item.hasSize = true;
1807                    }).on('error.mfploader', function() {
1808                         item.hasSize = true;
1809                         item.loadError = true;
1810                         _mfpTrigger('LazyLoadError', item);
1811                    }).attr('src', item.src);
1812               }
1813
1814
1815               item.preloaded = true;
1816          }
1817     }
1818});
1819
1820/*>>gallery*/
1821
1822/*>>retina*/
1823
1824var RETINA_NS = 'retina';
1825
1826$.magnificPopup.registerModule(RETINA_NS, {
1827     options: {
1828          replaceSrc: function(item) {
1829               return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
1830          },
1831          ratio: 1 // Function or number.  Set to 1 to disable.
1832     },
1833     proto: {
1834          initRetina: function() {
1835               if(window.devicePixelRatio > 1) {
1836
1837                    var st = mfp.st.retina,
1838                         ratio = st.ratio;
1839
1840                    ratio = !isNaN(ratio) ? ratio : ratio();
1841
1842                    if(ratio > 1) {
1843                         _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
1844                              item.img.css({
1845                                   'max-width': item.img[0].naturalWidth / ratio,
1846                                   'width': '100%'
1847                              });
1848                         });
1849                         _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
1850                              item.src = st.replaceSrc(item, ratio);
1851                         });
1852                    }
1853               }
1854
1855          }
1856     }
1857});
1858
1859/*>>retina*/
1860 _checkInstance(); }));
Note: See TracBrowser for help on using the repository browser.

Sites map