· 4 years ago · Mar 22, 2021, 10:48 AM
1/*! Magnific Popup - v1.2.0 - 2020-12-22
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, Array.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 = Array.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('function' === typeof 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">×</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('function' === typeof 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 img.srcset = item.el.find('img').attr('srcset');
1306 }
1307 item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError);
1308 img.src = item.src;
1309
1310 // without clone() "error" event is not firing when IMG is replaced by new IMG
1311 // TODO: find a way to avoid such cloning
1312 if(el.is('img')) {
1313 item.img = item.img.clone();
1314 }
1315
1316 img = item.img[0];
1317 if(img.naturalWidth > 0) {
1318 item.hasSize = true;
1319 } else if(!img.width) {
1320 item.hasSize = false;
1321 }
1322 }
1323
1324 mfp._parseMarkup(template, {
1325 title: _getTitle(item),
1326 img_replaceWith: item.img
1327 }, item);
1328
1329 mfp.resizeImage();
1330
1331 if(item.hasSize) {
1332 if(_imgInterval) clearInterval(_imgInterval);
1333
1334 if(item.loadError) {
1335 template.addClass('mfp-loading');
1336 mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
1337 } else {
1338 template.removeClass('mfp-loading');
1339 mfp.updateStatus('ready');
1340 }
1341 return template;
1342 }
1343
1344 mfp.updateStatus('loading');
1345 item.loading = true;
1346
1347 if(!item.hasSize) {
1348 item.imgHidden = true;
1349 template.addClass('mfp-loading');
1350 mfp.findImageSize(item);
1351 }
1352
1353 return template;
1354 }
1355 }
1356});
1357
1358/*>>image*/
1359
1360/*>>zoom*/
1361var hasMozTransform,
1362 getHasMozTransform = function() {
1363 if(hasMozTransform === undefined) {
1364 hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
1365 }
1366 return hasMozTransform;
1367 };
1368
1369$.magnificPopup.registerModule('zoom', {
1370
1371 options: {
1372 enabled: false,
1373 easing: 'ease-in-out',
1374 duration: 300,
1375 opener: function(element) {
1376 return element.is('img') ? element : element.find('img');
1377 }
1378 },
1379
1380 proto: {
1381
1382 initZoom: function() {
1383 var zoomSt = mfp.st.zoom,
1384 ns = '.zoom',
1385 image;
1386
1387 if(!zoomSt.enabled || !mfp.supportsTransition) {
1388 return;
1389 }
1390
1391 var duration = zoomSt.duration,
1392 getElToAnimate = function(image) {
1393 var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
1394 transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
1395 cssObj = {
1396 position: 'fixed',
1397 zIndex: 9999,
1398 left: 0,
1399 top: 0,
1400 '-webkit-backface-visibility': 'hidden'
1401 },
1402 t = 'transition';
1403
1404 cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;
1405
1406 newImg.css(cssObj);
1407 return newImg;
1408 },
1409 showMainContent = function() {
1410 mfp.content.css('visibility', 'visible');
1411 },
1412 openTimeout,
1413 animatedImg;
1414
1415 _mfpOn('BuildControls'+ns, function() {
1416 if(mfp._allowZoom()) {
1417
1418 clearTimeout(openTimeout);
1419 mfp.content.css('visibility', 'hidden');
1420
1421 // Basically, all code below does is clones existing image, puts in on top of the current one and animated it
1422
1423 image = mfp._getItemToZoom();
1424
1425 if(!image) {
1426 showMainContent();
1427 return;
1428 }
1429
1430 animatedImg = getElToAnimate(image);
1431
1432 animatedImg.css( mfp._getOffset() );
1433
1434 mfp.wrap.append(animatedImg);
1435
1436 openTimeout = setTimeout(function() {
1437 animatedImg.css( mfp._getOffset( true ) );
1438 openTimeout = setTimeout(function() {
1439
1440 showMainContent();
1441
1442 setTimeout(function() {
1443 animatedImg.remove();
1444 image = animatedImg = null;
1445 _mfpTrigger('ZoomAnimationEnded');
1446 }, 16); // avoid blink when switching images
1447
1448 }, duration); // this timeout equals animation duration
1449
1450 }, 16); // by adding this timeout we avoid short glitch at the beginning of animation
1451
1452
1453 // Lots of timeouts...
1454 }
1455 });
1456 _mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
1457 if(mfp._allowZoom()) {
1458
1459 clearTimeout(openTimeout);
1460
1461 mfp.st.removalDelay = duration;
1462
1463 if(!image) {
1464 image = mfp._getItemToZoom();
1465 if(!image) {
1466 return;
1467 }
1468 animatedImg = getElToAnimate(image);
1469 }
1470
1471 animatedImg.css( mfp._getOffset(true) );
1472 mfp.wrap.append(animatedImg);
1473 mfp.content.css('visibility', 'hidden');
1474
1475 setTimeout(function() {
1476 animatedImg.css( mfp._getOffset() );
1477 }, 16);
1478 }
1479
1480 });
1481
1482 _mfpOn(CLOSE_EVENT+ns, function() {
1483 if(mfp._allowZoom()) {
1484 showMainContent();
1485 if(animatedImg) {
1486 animatedImg.remove();
1487 }
1488 image = null;
1489 }
1490 });
1491 },
1492
1493 _allowZoom: function() {
1494 return mfp.currItem.type === 'image';
1495 },
1496
1497 _getItemToZoom: function() {
1498 if(mfp.currItem.hasSize) {
1499 return mfp.currItem.img;
1500 } else {
1501 return false;
1502 }
1503 },
1504
1505 // Get element postion relative to viewport
1506 _getOffset: function(isLarge) {
1507 var el;
1508 if(isLarge) {
1509 el = mfp.currItem.img;
1510 } else {
1511 el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
1512 }
1513
1514 var offset = el.offset();
1515 var paddingTop = parseInt(el.css('padding-top'),10);
1516 var paddingBottom = parseInt(el.css('padding-bottom'),10);
1517 offset.top -= ( $(window).scrollTop() - paddingTop );
1518
1519
1520 /*
1521
1522 Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.
1523
1524 */
1525 var obj = {
1526 width: el.width(),
1527 // fix Zepto height+padding issue
1528 height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
1529 };
1530
1531 // I hate to do this, but there is no another option
1532 if( getHasMozTransform() ) {
1533 obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
1534 } else {
1535 obj.left = offset.left;
1536 obj.top = offset.top;
1537 }
1538 return obj;
1539 }
1540
1541 }
1542});
1543
1544
1545
1546/*>>zoom*/
1547
1548/*>>iframe*/
1549
1550var IFRAME_NS = 'iframe',
1551 _emptyPage = '//about:blank',
1552
1553 _fixIframeBugs = function(isShowing) {
1554 if(mfp.currTemplate[IFRAME_NS]) {
1555 var el = mfp.currTemplate[IFRAME_NS].find('iframe');
1556 if(el.length) {
1557 // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
1558 if(!isShowing) {
1559 el[0].src = _emptyPage;
1560 }
1561
1562 // IE8 black screen bug fix
1563 if(mfp.isIE8) {
1564 el.css('display', isShowing ? 'block' : 'none');
1565 }
1566 }
1567 }
1568 };
1569
1570$.magnificPopup.registerModule(IFRAME_NS, {
1571
1572 options: {
1573 markup: '<div class="mfp-iframe-scaler">'+
1574 '<div class="mfp-close"></div>'+
1575 '<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+
1576 '</div>',
1577
1578 srcAction: 'iframe_src',
1579
1580 // we don't care and support only one default type of URL by default
1581 patterns: {
1582 youtube: {
1583 index: 'youtube.com',
1584 id: 'v=',
1585 src: '//www.youtube.com/embed/%id%?autoplay=1'
1586 },
1587 vimeo: {
1588 index: 'vimeo.com/',
1589 id: '/',
1590 src: '//player.vimeo.com/video/%id%?autoplay=1'
1591 },
1592 gmaps: {
1593 index: '//maps.google.',
1594 src: '%id%&output=embed'
1595 }
1596 }
1597 },
1598
1599 proto: {
1600 initIframe: function() {
1601 mfp.types.push(IFRAME_NS);
1602
1603 _mfpOn('BeforeChange', function(e, prevType, newType) {
1604 if(prevType !== newType) {
1605 if(prevType === IFRAME_NS) {
1606 _fixIframeBugs(); // iframe if removed
1607 } else if(newType === IFRAME_NS) {
1608 _fixIframeBugs(true); // iframe is showing
1609 }
1610 }// else {
1611 // iframe source is switched, don't do anything
1612 //}
1613 });
1614
1615 _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
1616 _fixIframeBugs();
1617 });
1618 },
1619
1620 getIframe: function(item, template) {
1621 var embedSrc = item.src;
1622 var iframeSt = mfp.st.iframe;
1623
1624 $.each(iframeSt.patterns, function() {
1625 if(embedSrc.indexOf( this.index ) > -1) {
1626 if(this.id) {
1627 if(typeof this.id === 'string') {
1628 embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
1629 } else {
1630 embedSrc = this.id.call( this, embedSrc );
1631 }
1632 }
1633 embedSrc = this.src.replace('%id%', embedSrc );
1634 return false; // break;
1635 }
1636 });
1637
1638 var dataObj = {};
1639 if(iframeSt.srcAction) {
1640 dataObj[iframeSt.srcAction] = embedSrc;
1641 }
1642 mfp._parseMarkup(template, dataObj, item);
1643
1644 mfp.updateStatus('ready');
1645
1646 return template;
1647 }
1648 }
1649});
1650
1651
1652
1653/*>>iframe*/
1654
1655/*>>gallery*/
1656/**
1657 * Get looped index depending on number of slides
1658 */
1659var _getLoopedId = function(index) {
1660 var numSlides = mfp.items.length;
1661 if(index > numSlides - 1) {
1662 return index - numSlides;
1663 } else if(index < 0) {
1664 return numSlides + index;
1665 }
1666 return index;
1667 },
1668 _replaceCurrTotal = function(text, curr, total) {
1669 return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
1670 };
1671
1672$.magnificPopup.registerModule('gallery', {
1673
1674 options: {
1675 enabled: false,
1676 arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
1677 preload: [0,2],
1678 navigateByImgClick: true,
1679 arrows: true,
1680
1681 tPrev: 'Previous (Left arrow key)',
1682 tNext: 'Next (Right arrow key)',
1683 tCounter: '%curr% of %total%'
1684 },
1685
1686 proto: {
1687 initGallery: function() {
1688
1689 var gSt = mfp.st.gallery,
1690 ns = '.mfp-gallery';
1691
1692 mfp.direction = true; // true - next, false - prev
1693
1694 if(!gSt || !gSt.enabled ) return false;
1695
1696 _wrapClasses += ' mfp-gallery';
1697
1698 _mfpOn(OPEN_EVENT+ns, function() {
1699
1700 if(gSt.navigateByImgClick) {
1701 mfp.wrap.on('click'+ns, '.mfp-img', function() {
1702 if(mfp.items.length > 1) {
1703 mfp.next();
1704 return false;
1705 }
1706 });
1707 }
1708
1709 _document.on('keydown'+ns, function(e) {
1710 if (e.keyCode === 37) {
1711 mfp.prev();
1712 } else if (e.keyCode === 39) {
1713 mfp.next();
1714 }
1715 });
1716 });
1717
1718 _mfpOn('UpdateStatus'+ns, function(e, data) {
1719 if(data.text) {
1720 data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
1721 }
1722 });
1723
1724 _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
1725 var l = mfp.items.length;
1726 values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
1727 });
1728
1729 _mfpOn('BuildControls' + ns, function() {
1730 if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
1731 var markup = gSt.arrowMarkup,
1732 arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS),
1733 arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS);
1734
1735 arrowLeft.on('click', function() {
1736 mfp.prev();
1737 });
1738 arrowRight.on('click', function() {
1739 mfp.next();
1740 });
1741
1742 mfp.container.append(arrowLeft.add(arrowRight));
1743 }
1744 });
1745
1746 _mfpOn(CHANGE_EVENT+ns, function() {
1747 if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);
1748
1749 mfp._preloadTimeout = setTimeout(function() {
1750 mfp.preloadNearbyImages();
1751 mfp._preloadTimeout = null;
1752 }, 16);
1753 });
1754
1755
1756 _mfpOn(CLOSE_EVENT+ns, function() {
1757 _document.off(ns);
1758 mfp.wrap.off('click'+ns);
1759 mfp.arrowRight = mfp.arrowLeft = null;
1760 });
1761
1762 },
1763 next: function() {
1764 mfp.direction = true;
1765 mfp.index = _getLoopedId(mfp.index + 1);
1766 mfp.updateItemHTML();
1767 },
1768 prev: function() {
1769 mfp.direction = false;
1770 mfp.index = _getLoopedId(mfp.index - 1);
1771 mfp.updateItemHTML();
1772 },
1773 goTo: function(newIndex) {
1774 mfp.direction = (newIndex >= mfp.index);
1775 mfp.index = newIndex;
1776 mfp.updateItemHTML();
1777 },
1778 preloadNearbyImages: function() {
1779 var p = mfp.st.gallery.preload,
1780 preloadBefore = Math.min(p[0], mfp.items.length),
1781 preloadAfter = Math.min(p[1], mfp.items.length),
1782 i;
1783
1784 for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
1785 mfp._preloadItem(mfp.index+i);
1786 }
1787 for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
1788 mfp._preloadItem(mfp.index-i);
1789 }
1790 },
1791 _preloadItem: function(index) {
1792 index = _getLoopedId(index);
1793
1794 if(mfp.items[index].preloaded) {
1795 return;
1796 }
1797
1798 var item = mfp.items[index];
1799 if(!item.parsed) {
1800 item = mfp.parseEl( index );
1801 }
1802
1803 _mfpTrigger('LazyLoad', item);
1804
1805 if(item.type === 'image') {
1806 item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
1807 item.hasSize = true;
1808 }).on('error.mfploader', function() {
1809 item.hasSize = true;
1810 item.loadError = true;
1811 _mfpTrigger('LazyLoadError', item);
1812 }).attr('src', item.src);
1813 }
1814
1815
1816 item.preloaded = true;
1817 }
1818 }
1819});
1820
1821/*>>gallery*/
1822
1823/*>>retina*/
1824
1825var RETINA_NS = 'retina';
1826
1827$.magnificPopup.registerModule(RETINA_NS, {
1828 options: {
1829 replaceSrc: function(item) {
1830 return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
1831 },
1832 ratio: 1 // Function or number. Set to 1 to disable.
1833 },
1834 proto: {
1835 initRetina: function() {
1836 if(window.devicePixelRatio > 1) {
1837
1838 var st = mfp.st.retina,
1839 ratio = st.ratio;
1840
1841 ratio = !isNaN(ratio) ? ratio : ratio();
1842
1843 if(ratio > 1) {
1844 _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
1845 item.img.css({
1846 'max-width': item.img[0].naturalWidth / ratio,
1847 'width': '100%'
1848 });
1849 });
1850 _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
1851 item.src = st.replaceSrc(item, ratio);
1852 });
1853 }
1854 }
1855
1856 }
1857 }
1858});
1859
1860/*>>retina*/
1861 _checkInstance(); }));
1862