Записи с меткой "Lightbox"
Magnific Popup
Вы можете получить файл Magnific Popup JS и CSS из dist/папки в репозитории GitHub или скомпилировать его самостоятельно с помощью Grunt.
<!-- Magnific Popup core CSS file --><link rel="stylesheet" href="magnific-popup/magnific-popup.css">
<!-- jQuery 1.7.2+ or Zepto.js 1.0+ --><script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- Magnific Popup core JS file --><script src="magnific-popup/jquery.magnific-popup.js"></script>
Это не требуется, но мы рекомендуем размещать файлы CSS и файлы <head>JavaScript и код инициализации в нижнем колонтитуле вашего сайта (перед закрывающим </body>тегом).
Если у вас уже есть jquery.jsна вашем сайте, не включайте его во второй раз или используйте jQuery.noConflict();режим. При желании вы можете включить Zepto.js вместо jQuery или выбрать, какой из них следует включить на основе поддержки браузера.
Инициализация всплывающего окна
Код инициализации всплывающего окна должен быть выполнен после готовности документа, например:
$(document).ready(function() {
$('.image-link').magnificPopup({type:'image'});});
Существует три способа инициализации всплывающего окна:
1. Из HTML-элемента
<a class="test-popup-link" href="path-to-image.jpg">Open popup</a>
$('.test-popup-link').magnificPopup({
type: 'image'
// other options});
2. Из группы элементов с одним родителем
То же, что и первый, но используйте этот метод, если вы создаете всплывающее окно из списка элементов в одном контейнере. Обратите внимание, что этот метод не включает режим галереи, он просто уменьшает количество обработчиков событий кликов; каждый элемент будет открыт как одно всплывающее окно. Если вы хотите включить галерею, добавьте эту gallery:{enabled:true} опцию.
<div class="parent-container">
<a href="path-to-image-1.jpg">Open popup 1</a>
<a href="path-to-image-2.jpg">Open popup 2</a>
<a href="path-to-image-3.jpg">Open popup 3</a></div>
$('.parent-container').magnificPopup({
delegate: 'a', // child items selector, by clicking on it popup will open
type: 'image'
// other options});
3. Из опции «items»
items Параметр определяет данные для всплывающего элемента (ов) и делает Magnific Popup игнорировать все атрибуты целевого DOM элемента. Значение itemsможет быть единственным объектом или массивом объектов.
// Example with single object$('#some-button').magnificPopup({
items: {
src: 'path-to-image-1.jpg'
},
type: 'image' // this is default type});
// Example with multiple objects$('#some-button').magnificPopup({
items: [
{
src: 'path-to-image-1.jpg'
},
{
src: 'http://vimeo.com/123123';,
type: 'iframe' // this overrides default type
},
{
src: $('<div>Dynamically created element</div>'), // Dynamically created element
type: 'inline'
},
{
src: '<div>HTML string</div>',
type: 'inline'
},
{
src: '#my-popup', // CSS selector of an element on page that should be used as a popup
type: 'inline'
}
],
gallery: {
enabled: true
},
type: 'image' // this is default type});
Типы контента
По умолчанию Magnific Popup имеет четыре типа контента: image, iframe, inline, и ajax. Нет никакого «автоматического обнаружения» типа на основе URL-адреса, поэтому вы должны определить его вручную.
Тип всплывающего окна можно определить двумя способами:
-
Использование type опции. Например: $('.image-link').magnificPopup({type:'image'}).
-
Использование mfp-TYPE класса CSS (где TYPE- желаемый тип контента). Например: <a class="mfp-image image-link">Open image</a>, $('.image-link').magnificPopup().
Второй вариант всегда переопределяет первый, поэтому вы можете инициализировать всплывающие окна с несколькими типами контента с одного вызова.
inline является типом содержимого по умолчанию (из версии 0.8.4), поэтому вы можете пропустить его определение.
Источник всплывающего содержимого (например, путь к изображению, путь к файлу HTML, путь к странице видео) можно определить несколькими способами:
Метод №1: Из href атрибута:
<a href="image-for-popup.jpg">Open image</a>Метод №2: Из data-mfp-src атрибута (переопределяет первый метод):
<a href="some-image.jpg" data-mfp-src="image-for-popup.jpg">Open image</a>Метод №3: Из items опции
$.magnificPopup.open({
items: {
src: 'some-image.jpg'
},
type: 'image'});
Если вы хотите изменить способ анализа исходного кода, вы можете подключиться к elementParse обратному вызову. Например:
$('.image-link').magnificPopup({
type:'image',
callbacks: {
elementParse: function(item) {
// Function will fire for each target element
// "item.el" is a target DOM element (if present)
// "item.src" is a source that you may modify
console.log(item); // Do whatever you want with "item" object
}
}});
Путь к изображению должен быть установлен в качестве основного источника, если вы выбрали этот тип. Если ваше всплывающее окно не имеет источника изображения и не имеет изображения, которое не должно быть предварительно загружено (и сетчатки и т. Д.), Используйте этот inline тип. Тип изображения
image: {
markup: '<div class="mfp-figure">'+
'<div class="mfp-close"></div>'+
'<div class="mfp-img"></div>'+
'<div class="mfp-bottom-bar">'+
'<div class="mfp-title"></div>'+
'<div class="mfp-counter"></div>'+
'</div>'+
'</div>', // Popup HTML markup. `.mfp-img` div will be replaced with img tag, `.mfp-close` by close button
cursor: 'mfp-zoom-out-cur', // Class that adds zoom cursor, will be added to body. Set to null to disable zoom out cursor.
titleSrc: 'title', // Attribute of the target element that contains caption for the slide.
// Or the function that should return the title. For example:
// titleSrc: function(item) {
// return item.el.attr('title') + '<small>by Marsel Van Oosten</small>';
// }
verticalFit: true, // Fits image in area vertically
tError: '<a href="%url%">The image</a> could not be loaded.' // Error message}
Тип iframe
Обратите внимание, что Magnific Popup не реализует кеширование на стороне клиента на основе JavaScript для изображений. Поэтому убедитесь, что ваш сервер добавляет заголовки, чтобы изображение не загружалось каждый раз.
По умолчанию Magnific Popup поддерживает только один тип URL для каждой службы:
// YouTube"http://www.youtube.com/watch?v=7HKoqNJtMTQ";
// Vimeo"http://vimeo.com/123123";
// Google Maps"https://maps.google.com/maps?q=221B+Baker+Street,+London,+United+Kingdom&hl=en&t=v&hnear=221B+Baker+St,+London+NW1+6XE,+United+Kingdom";
Но вы можете расширить его и полностью поддержать любой URL или любую другую услугу. Варианты iframe:
iframe: {
markup: '<div class="mfp-iframe-scaler">'+
'<div class="mfp-close"></div>'+
'<iframe class="mfp-iframe" frameborder="0" allowfullscreen></iframe>'+
'</div>', // HTML markup of popup, `mfp-close` will be replaced by the close button
patterns: {
youtube: {
index: 'youtube.com/', // String that detects type of video (in this case YouTube). Simply via url.indexOf(index).
id: 'v=', // String that splits URL in a two parts, second part should be %id%
// Or null - full URL will be returned
// Or a function that should return %id%, for example:
// id: function(url) { return 'parsed id'; }
src: '//www.youtube.com/embed/%id%?autoplay=1';; // URL that will be set as a source for iframe.
},
vimeo: {
index: 'vimeo.com/',
id: '/',
src: '//player.vimeo.com/video/%id%?autoplay=1'
},
gmaps: {
index: '//maps.google.',
src: '%id%&output=embed'
}
// you may add here more sources
},
srcAction: 'iframe_src', // Templating object key. First part defines CSS selector, second attribute. "iframe_src" means: find "iframe" and set attribute "src".}
Чтобы создать всплывающее окно из встроенного элемента, вам необходимо:
Встроенный тип
1) Создайте HTML-элемент, который вы хотите отобразить во всплывающем меню, и добавьте его где-нибудь. Класс mfp-hideдолжен скрывать всплывающее окно со страницы.
<div id="test-popup" class="white-popup mfp-hide">
Popup content
</div>
2) Стиль этого элемента. Magnific Popup по умолчанию не применяет к нему никаких стилей, кроме вертикального центрирования (если alignTop:false). Кнопка закрытия автоматически добавляется внутри (если closeBtnInside:true).
.white-popup {
position: relative;
background: #FFF;
padding: 20px;
width: auto;
max-width: 500px;
margin: 20px auto;}
3) Кнопка добавления, которая откроет всплывающее окно (источник должен соответствовать идентификатору CSS элемента ( #test-popupв нашем случае).
<!-- Like so: --><a href="#test-popup" class="open-popup-link">Show inline popup</a>
<!-- Or like so: --><a href="mobile-friendly-page.html" data-mfp-src="#test-popup" class="open-popup-link">Show inline popup</a>
4) Инициализировать скрипт.
$('.open-popup-link').magnificPopup({
type:'inline',
midClick: true // Allow opening popup on middle mouse click. Always set it to true if you don't provide alternative source in href.});
Вот несколько других способов инициализации всплывающего окна:
// From HTML string$('button').magnificPopup({
items: {
src: '<div class="white-popup">Dynamically created popup</div>',
type: 'inline'
}});
// From an element with ID #popup$('button').magnificPopup({
items: {
src: '#popup',
type: 'inline'
}});
// From jQuery object$('button').magnificPopup({
items: {
src: $('<div class="white-popup">Dynamically created popup</div>'),
type: 'inline'
}});
// Open directly via API$.magnificPopup.open({
items: {
src: '<div class="white-popup">Dynamically created popup</div>', // can be a HTML string, jQuery object, or CSS selector
type: 'inline'
}});
Я создал два примера в CodePen, которые помогут вам лучше понять, как это работает:
Тип Ajax
Чтобы создать такой тип всплывающего окна, сначала укажите путь к файлу, который вы хотите отобразить, и выберите ajaxтип всплывающего окна. Сам всплывающий режим должен быть создан точно так же, как встроенный всплывающий тип .
Важная заметка! Содержимое загружаемого файла уже является всплывающим, поэтому должен быть только один корневой элемент .
<a href="path-to-file.html" class="ajax-popup-link">Show inline popup</a>
$('.ajax-popup-link').magnificPopup({
type: 'ajax'});
Обратите внимание, что путь к файлу, который будет загружен, должен иметь одинаковое происхождение (например, находиться в одном домене).
Варианты Ajax:
ajax: {
settings: null, // Ajax settings object that will extend default one - http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
// For example:
// settings: {cache:false, async:false}
cursor: 'mfp-ajax-cur', // CSS class that will be added to body during the loading (adds "progress" cursor)
tError: '<a href="%url%">The content</a> could not be loaded.' // Error message, can contain %curr% and %total% tags if gallery is enabled}
callbacks: {Чтобы изменить содержимое после его загрузки или выбрать и показать только определенный элемент из загруженного файла, есть parseAjaxобратный вызов:
parseAjax: function(mfpResponse) {
// mfpResponse.data is a "data" object from ajax "success" callback
// for simple HTML file, it will be just String
// You may modify it to change contents of the popup
// For example, to show just #some-element:
// mfpResponse.data = $(mfpResponse.data).find('#some-element');
// mfpResponse.data must be a String or a DOM (jQuery) element
console.log('Ajax content loaded:', mfpResponse);
},
ajaxContentAdded: function() {
// Ajax content is loaded and appended to DOM
console.log(this.content);
}}
Параметры должны быть переданы в код инициализации и разделены запятой, например:
Опции
$('.some-link').magnificPopup({
// main options
disableOn: 400,
key: 'some-key',
gallery: {
// options for gallery
enabled: true
},
image: {
// options for image content type
titleSrc: 'title'
}
});
disableOn Параметры для определенных модулей объясняются в разделах документации (например, связанные с текстом в разделе перевода , связанные с галереей, находятся в разделе галереи . Здесь вы можете найти список общих параметров:
nullЕсли ширина окна меньше, чем номер в этой опции, лайтбокс не будет открыт, и поведение элемента по умолчанию будет запущено. Установите для 0отключения поведения. Опция работает только при инициализации Magnific Popup из элемента DOM.
Может также принимать функцию как параметр, который должен быть возвращен, trueесли лайтбокс можно открыть и falseиначе. Например:
disableOn: function() {
if( $(window).width() < 600 ) {
return false;
}
return true;}
null ключ
Опция «Ключ» является уникальным идентификатором одной или группы всплывающих окон с одинаковой структурой. Если вы его не определите, элементы DOM будут создаваться и уничтожаться каждый раз при открытии и закрытии всплывающего окна.
Вы можете (и должны) установить равный ключ для разных всплывающих окон, если их разметка совпадает. По разметке я имею в виду опции, которые изменяют структуру HTML всплывающего окна (например, закрытие значка и его HTML-код).
Например: у вас много всплывающих окон, которые показывают название, текст и кнопку - вы можете использовать один ключ для всех из них, поэтому создается только один экземпляр этого элемента. То же самое для всплывающего окна, которое всегда содержит изображение и подпись.
Вы можете удалить кэшированные шаблоны следующим образом:
// delete template with key "your-key"
delete $.magnificPopup.instance.popupsCache['your-key'];
// delete all templates
$.magnificPopup.instance.popupsCache = {};
midClick
falseЕсли установить trueлайтбокс, откроется, если пользователь нажал среднюю кнопку мыши или нажал клавишу Command / Ctrl. Опция работает только при инициализации Magnific Popup из элемента DOM.
MainClass
empty stringСтрока, которая содержит классы, которые будут добавлены в корневой элемент всплывающей оболочки и в темное наложение. Например "myClass", может также содержать несколько классов - 'myClassOne myClassTwo'.
Прелоадер
truePreloader в Magnific Popup используется как индикатор текущего состояния. Если опция включена, она всегда присутствует в DOM, только текст внутри нее изменяется. Ниже вы можете увидеть объяснение имен CSS, которые применяются к контейнеру, который содержит область preloader и content в зависимости от состояния текущего элемента:
/* Content loading is in progress */.mfp-s-loading { }
/* Content successfully loaded */.mfp-s-ready { }
/* Error during loading */.mfp-s-error { }
Например, если вы хотите, чтобы ваше сообщение об ошибке было красным, добавьте такой CSS:
.mfp-s-error .mfp-preloader {
color: red;}
Вы можете вызвать изменение статуса вручную, позвонив instance.updateStatus ('error', 'error message').
Фокус
empty stringСтрока с CSS-селектором элемента внутри всплывающего окна, которое должно быть сфокусировано. В идеале это должен быть первый элемент всплывающего окна, который можно сфокусировать. Например, 'input'или '#login-input'. Оставьте пустым, чтобы сфокусировать всплывающее окно.
closeOnContentClick
falseЗакрыть всплывающее окно, когда пользователь нажимает на его содержимое. Рекомендуется включить эту опцию, когда у вас есть только изображение во всплывающем окне.
closeOnBgClick
trueЗакройте всплывающее окно, когда пользователь нажимает на темную оверлей.
closeBtnInside
trueЕсли включено, Magnific Popup поместит закрытую кнопку внутри содержимого всплывающего окна, а оболочка получит класс mfp-close-btn-in(который в файле CSS по умолчанию делает цвет его изменения). Если разметка всплывающего элемента определяется элементом класса, mfp-closeон будет заменен этой кнопкой, иначе кнопка закрытия будет добавлена напрямую.
showCloseBtn
trueУправляет отображением кнопки закрытия или нет.
enableEscapeKey
trueКонтролирует, будет ли нажатие клавиши эвакуации отменять активное всплывающее окно или нет.
модальный
falseКогда установлено значение true, всплывающее окно будет иметь модальное поведение: его невозможно будет отменить обычным способом (кнопка закрытия, клавиша эвакуации или щелчок на наложении).
Это ярлык , чтобы установить closeOnContentClick, closeOnBgClick, showCloseBtnи enableEscapeKeyк false.
AlignTop
falseЕсли установлено trueвсплывающее окно, выровнено сверху, а не центрировано. (в основном, этот параметр добавляет mfp-align-topCSS-класс в popup, который удаляет стили, которые выравнивают всплывающее окно в центр).
Индекс
nullИспользуется для галереи. Определяет начальный индекс. Если всплывающее окно инициализировано из элемента DOM, этот параметр будет проигнорирован.
fixedContentPos
autoПоложение содержимого всплывающих окон. Может быть "auto", trueили false. Если установлено значение true- фиксированная позиция будет использоваться, false- - абсолютная позиция на основе текущей прокрутки. Если установлено "auto"всплывающее окно, оно автоматически отключит этот параметр, если браузер не поддерживает фиксированную позицию должным образом.
fixedBgPos
autoТо же, что и выше, но определяет свойство позиции темного переливного наложения. Если установлено значение false- будет генерироваться огромный высокий оверлей, который равен высоте окна для имитации фиксированной позиции. Рекомендуется установить этот параметр, trueесли вы анимируете этот темный оверлей и контент, скорее всего, не будет увеличен, так как размер его будет намного меньше.
overflowY
autoОпределяет полосу прокрутки из всплывающего меню, работает как переполнение-у CSS собственности - любое CSS приемлемое значение допускается (например auto, scroll, hidden). Опция применяется только при включенной фиксированной позиции.
Варианта нет overflowX, но вы можете легко подражать ему только через CSS.
removalDelay
0Задержка перед всплыванием удаляется из DOM. Используется для анимации .
closeMarkup
<button title="%title%" type="button" class="mfp-close">×</button>Разметка кнопки закрытия. % title% будет заменено опцией tClose.
prependTo
document.bodyЭлемент DOM, к которому будет добавлено всплывающее окно. Полезно, когда вы используете ASP.NET, где всплывающее окно должно быть внутри form. Вариант доступен с 2013/12/04.
autoFocusLast
trueЕсли задать trueпоследний сфокусированный элемент, прежде чем всплывающее окно будет сфокусировано после закрытия всплывающего окна. Вариант доступен с 2015/12/16.
Галерея
Модуль галереи позволяет вам переключать содержимое всплывающего окна и добавлять стрелки навигации. Он может переключать и смешивать любые типы контента, а не только изображения. Параметры галереи:
gallery: {
enabled: false, // set to true to enable gallery
preload: [0,2], // read about this option in next Lazy-loading section
navigateByImgClick: true,
arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>', // markup of an arrow button
tPrev: 'Previous (Left arrow key)', // title for left button
tNext: 'Next (Right arrow key)', // title for right button
tCounter: '<span class="mfp-counter">%curr% of %total%</span>' // markup of counter}
Пример:
// This will create a single gallery from all elements that have class "gallery-item"$('.gallery-item').magnificPopup({
type: 'image',
gallery:{
enabled:true
}});
Несколько галерей
Чтобы иметь несколько галерей на странице, вам нужно создать новый экземпляр Magnific Popup для каждой отдельной галереи. Например
<div class="gallery">
<a href="path-to-image.jpg">Open image 1 (gallery #1)</a>
<a href="path-to-image.jpg">Open image 2 (gallery #1)</a></div><div class="gallery">
<a href="path-to-image.jpg">Open image 1 (gallery #2)</a>
<a href="path-to-image.jpg">Open image 2 (gallery #2)</a>
<a href="http://vimeo.com/123123"; class="mfp-iframe">Open video (gallery #2). Class mfp-iframe forces "iframe" content type on this item.</a></div>
$('.gallery').each(function() { // the containers for all your galleries
$(this).magnificPopup({
delegate: 'a', // the selector for gallery item
type: 'image',
gallery: {
enabled:true
}
});});
Вам необязательно использовать delegateопцию, это может быть просто $(this).find('a').magnificPopup( ....
Ленивая загрузка
Опция «ленивая загрузка» предварительно загружает соседние предметы. Он принимает массив с двумя целыми числами. Первое - это количество элементов для предварительной загрузки перед текущим. Второе - количество изображений, которые нужно предварительно загрузить после тока. Например, preload: [1,3]загрузите 3 следующих элемента и 1, которые находятся перед током. Эти значения автоматически переключаются в зависимости от направления движения.
По умолчанию все, что он делает, это просто поиск тега изображения и предварительная загрузка его с помощью JavaScript. Но вы можете расширить его и выполнить свою пользовательскую логику предварительной загрузки с помощью lazyLoadсобытия, например:
callbacks: {
lazyLoad: function(item) {
console.log(item); // Magnific Popup data object that should be loaded
}}
Опция «Предварительная загрузка» может быть изменена динамически. Чтобы отключить его preload:0.
Анимация
Анимация может быть добавлена в любой пример. Анимационная анимация на основе Ajax анимация запускается только после загрузки содержимого.
После всплывающего всплывающего всплывающего окна и фонового наложения получите класс mfp-ready. Прежде чем удалять всплывающие окна, они получают класс mfp-removing.
Например:
// Initialize popup as usual$('.popup-link').magnificPopup({
// Delay in milliseconds before popup is removed
removalDelay: 300,
// Class that is added to popup wrapper and background
// make it unique to apply your CSS animations just to this exact popup
mainClass: 'mfp-fade'});
Затем просто играйте с переходами CSS3:
/* overlay at start */.mfp-fade.mfp-bg {
opacity: 0;
-webkit-transition: all 0.15s ease-out;
-moz-transition: all 0.15s ease-out;
transition: all 0.15s ease-out;}/* overlay animate in */.mfp-fade.mfp-bg.mfp-ready {
opacity: 0.8;}/* overlay animate out */.mfp-fade.mfp-bg.mfp-removing {
opacity: 0;}
/* content at start */.mfp-fade.mfp-wrap .mfp-content {
opacity: 0;
-webkit-transition: all 0.15s ease-out;
-moz-transition: all 0.15s ease-out;
transition: all 0.15s ease-out;}/* content animate it */.mfp-fade.mfp-wrap.mfp-ready .mfp-content {
opacity: 1;}/* content animate out */.mfp-fade.mfp-wrap.mfp-removing .mfp-content {
opacity: 0;}
Используйте анимацию мудро и когда это действительно необходимо. Не включайте его, когда ваше всплывающее окно может содержать большое изображение или много текста HTML.
Сетчатка
Модуль «Retina» позволяет отображать изображения с высоким разрешением на экранах с высоким разрешением devicePixelRatio. Модуль работает только с типом «изображение» и только когда window.devicePixelRatio > 1.
Сначала подготовьте два набора изображений. Поддерживаемый по умолчанию синтаксис требует @2x в конце имени файла изображения, например: image.jpg> image@2x.jpg. Затем инициализируйте всплывающее окно, как обычно, и добавьте ratioнабор параметров сетчатки.
<a href="image.jpg" class="image-link">Open popup</a>
// Initialize popup as usual$('.image-link').magnificPopup({
type: 'image',
retina: {
ratio: 1, // Increase this number to enable retina image support.
// Image in popup will be scaled down by this number.
// Option can also be a function which should return a number (in case you support multiple ratios). For example:
// ratio: function() { return window.devicePixelRatio === 1.5 ? 1.5 : 2 }
replaceSrc: function(item, ratio) {
return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
} // function that changes image source
}
});
Просмотрите пример появления сетчатки на CodePen .
Эффект масштабирования
Масштабирование работает только для изображений, пока. Чтобы добавить эффект масштабирования, сначала убедитесь, что вы включили модуль масштабирования в сборку Magnific Popup (с версии v.1.9.1). Затем выполните следующие шаги:
1) Добавьте эскиз со ссылкой, которая откроет всплывающее окно, например:
<a href="image.jpg" class="image-link">
<img src="thumbnails.jpg" /></a>
Вы должны убедиться, что отношение вашего миниатюры соответствует соотношению большого изображения, чтобы избежать «прыжков» в конце анимации масштабирования.
2) Инициализировать всплывающее окно с zoomопциями:
// Initialize popup as usual$('.image-link').magnificPopup({
type: 'image',
mainClass: 'mfp-with-zoom', // this class is for CSS animation below
zoom: {
enabled: true, // By default it's false, so don't forget to enable it
duration: 300, // duration of the effect, in milliseconds
easing: 'ease-in-out', // CSS transition easing function
// The "opener" function should return the element from which popup will be zoomed in
// and to which popup will be scaled down
// By defailt it looks for an image tag:
opener: function(openerElement) {
// openerElement is the element on which popup was initialized, in this case its <a> tag
// you don't need to add "opener" option if this code matches your needs, it's defailt one.
return openerElement.is('img') ? openerElement : openerElement.find('img');
}
}
});
3) При желании добавьте анимацию затухания CSS в фоновый оверлей
.mfp-with-zoom .mfp-container,.mfp-with-zoom.mfp-bg {
opacity: 0;
-webkit-backface-visibility: hidden;
/* ideally, transition speed should match zoom duration */
-webkit-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
-o-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;}
.mfp-with-zoom.mfp-ready .mfp-container {
opacity: 1;}.mfp-with-zoom.mfp-ready.mfp-bg {
opacity: 0.8;}
.mfp-with-zoom.mfp-removing .mfp-container,.mfp-with-zoom.mfp-removing.mfp-bg {
opacity: 0;}
Модуль Zoom добавляет zoomAnimationEnded обратный вызов, который срабатывает при завершении анимации увеличения.
API
Существует гораздо больший список общедоступных событий, методов и переменных, чем приведенный здесь, который используется для разработки модулей, загляните внутрь кода или введите консоль, $.magnificPopup.instance.чтобы найти их, если вы считаете, что что-то должно быть добавлено в документы - пожалуйста, отправьте коммит.
Мероприятия
Вы можете определить обратные вызовы в callbacksопции. Кроме того, все события Magnific Popup также отправляются с использованием triggerHandlerцелевого элемента (или документа, если элемент не существует).
$('.image-link').magnificPopup({
// you may add other options here, e.g.:
preloader: true,
callbacks: {
open: function() {
// Will fire when this exact popup is opened
// this - is Magnific Popup object
},
close: function() {
// Will fire when popup is closed
}
// e.t.c.
}});
// Alternative method: using events// Name of event should start from `mfp` and the first letter should be uppercase.// e.g. 'open' becomes 'mfpOpen', 'beforeOpen' becomes 'mfpBeforeOpen'.$('.image-link').on('mfpOpen', function(e /*, params */) {
console.log('Popup opened', $.magnificPopup.instance);});
Список обратных вызовов. В каждом обратном вызове thisесть $.magnificPopup.instance, так что вы можете выполнять методы (this.close()) или общедоступные переменные (this.currItem).
callbacks: {
beforeOpen: function() {
console.log('Start of popup initialization');
},
elementParse: function(item) {
// Function will fire for each target element
// "item.el" is a target DOM element (if present)
// "item.src" is a source that you may modify
console.log('Parsing content. Item object that is being parsed:', item);
},
change: function() {
console.log('Content changed');
console.log(this.content); // Direct reference to your popup element
},
resize: function() {
console.log('Popup resized');
// resize event triggers only when height is changed or layout forced
},
open: function() {
console.log('Popup is opened');
},
beforeClose: function() {
// Callback available since v0.9.0
console.log('Popup close has been initiated');
},
close: function() {
console.log('Popup removal initiated (after removalDelay timer finished)');
},
afterClose: function() {
console.log('Popup is completely closed');
},
markupParse: function(template, values, item) {
// Triggers each time when content of popup changes
// console.log('Parsing:', template, values, item);
},
updateStatus: function(data) {
console.log('Status changed', data);
// "data" is an object that has two properties:
// "data.status" - current status type, can be "loading", "error", "ready"
// "data.text" - text that will be displayed (e.g. "Loading...")
// you may modify this properties to change current status or its text dynamically
},
imageLoadComplete: function() {
// fires when image in current popup finished loading
// avaiable since v0.9.0
console.log('Image loaded');
},
// Only for ajax popup type
parseAjax: function(mfpResponse) {
// mfpResponse.data is a "data" object from ajax "success" callback
// for simple HTML file, it will be just String
// You may modify it to change contents of the popup
// For example, to show just #some-element:
// mfpResponse.data = $(mfpResponse.data).find('#some-element');
// mfpResponse.data must be a String or a DOM (jQuery) element
console.log('Ajax content loaded:', mfpResponse);
},
ajaxContentAdded: function() {
// Ajax content is loaded and appended to DOM
console.log(this.content);
}}
Общественные методы
// Open popup immediately. If popup is already opened - it'll just overwite the content (but old options will be kept).// - first parameter: options object// - second parameter (optional): index of item to open$.magnificPopup.open({
items: {
src: 'someimage.jpg'
},
type: 'image'
// You may add options here, they're exactly the same as for $.fn.magnificPopup call
// Note that some settings that rely on click event (like disableOn or midClick) will not work here}, 0);
$.magnificPopup.close(); // Close popup that is currently opened (shorthand)
/* Methods below don't have shorthand like "open" and "close". They should be called through "instance" object. "instance" is available only when at least one popup was opened. For example: $.magnificPopup.instance.doSomething();*/
var magnificPopup = $.magnificPopup.instance; // save instance in magnificPopup variable
magnificPopup.close(); // Close popup that is currently opened
// Navigation when gallery is enabledmagnificPopup.next(); // go to next itemmagnificPopup.prev(); // go to prev itemmagnificPopup.goTo(4); // go to item #4
magnificPopup.updateItemHTML(); // updates the popup content. Useful after you change "items" array
// Update status of popup// First param: status type, can be: 'loading', 'error' or 'ready'.// Second param: message that will be displayed.magnificPopup.updateStatus('loading', 'The loading text...');
Вы также можете вызвать ЛЮБОЙ метод через $.fn.magnificPopup('methodName' /*, param1, param2 ... */) после инициализации всплывающего окна, например:
// First of make sure that you initialized popup on element $('.element-with-popup')
// Then$('.element-with-popup').magnificPopup('open'); // Will open the popup$('.element-with-popup').magnificPopup('open', 5); // Will open popup with 5th item$('.element-with-popup').magnificPopup('next');$('.element-with-popup').magnificPopup('goTo', 3);
Вы также можете открыть всплывающее окно непосредственно при инициализации:
$('.element-with-popup').magnificPopup({
items: {
src: 'path-to-image.jpg',
type: 'image'
}
// (optionally) other options}).magnificPopup('open');
Общественные объекты
Большинство свойств доступны только после всплывания. Здесь перечислены только самые используемые.
var magnificPopup = $.magnificPopup.instance;
magnificPopup.items // array that holds data for popup itemsmagnificPopup.currItem // data for current itemmagnificPopup.index // current item index (integer)
magnificPopup.content // direct reference to jQuery DOM element that you open in popupmagnificPopup.bgOverlay // transluscent overlaymagnificPopup.wrap // container that holds all controls and contentContainermagnificPopup.contentContainer // container that holds popup content, child of wrap
magnificPopup.st.el // Target clicked element that opened popup (works if popup is initialized from DOM element)magnificPopup.st.mainEl // Main element (or collection of elements) from which popup was initialized (--''--)
magnificPopup.isIE7magnificPopup.isIOS
Идет перевод
Интернационализация Magnific Popup очень проста, все, что вам нужно, это расширить объект настроек по умолчанию с новыми значениями или просто передать параметры вашему коду инициализации. Если вы создаете публичный плагин или тему, настоятельно рекомендуется использовать только второй метод, чтобы избежать конфликтов.
Некоторые свойства содержат% keys%, которые не должны быть переведены, но могут быть переупорядочены или удалены.
// Add it after jquery.magnific-popup.js and before first initialization code$.extend(true, $.magnificPopup.defaults, {
tClose: 'Close (Esc)', // Alt text on close button
tLoading: 'Loading...', // Text that is displayed during loading. Can contain %curr% and %total% keys
gallery: {
tPrev: 'Previous (Left arrow key)', // Alt text on left arrow
tNext: 'Next (Right arrow key)', // Alt text on right arrow
tCounter: '%curr% of %total%' // Markup for "1 of 7" counter
},
image: {
tError: '<a href="%url%">The image</a> could not be loaded.' // Error message when image could not be loaded
},
ajax: {
tError: '<a href="%url%">The content</a> could not be loaded.' // Error message when ajax request failed
}});
То же самое, но применяется только к определенному слайдеру:
$('.some-button').magnificPopup({
tClose: 'Close (Esc)',
tLoading: 'Loading...',
gallery: {
tPrev: 'Previous (Left arrow key)',
tNext: 'Next (Right arrow key)',
tCounter: '%curr% of %total%'
},
image: {
tError: '<a href="%url%">The image</a> could not be loaded.'
},
ajax: {
tError: '<a href="%url%">The request</a> failed.'
}
// surely, you may add other options here
});
Вопросы-Ответы
Как разместить галерею навигация стрелки «внутри» изображения?
Как переопределить некоторые функции без изменения исходных файлов?
Перепишите функцию, которую вы хотите изменить, отредактировав объект Magnific Popup, вы можете получить к нему доступ так $.magnificPopup.instance. Например, чтобы переопределить функцию, которая переходит в «следующий» элемент в галерее:
// add this code after popup JS file is included$.magnificPopup.instance.next = function() {
// Do something
// You may call parent ("original") method like so:
$.magnificPopup.proto.next.call(this /*, optional arguments */);};
Вы можете переопределить любую публичную функцию, просто отметьте, что это изменение применяется во всем мире.
Magnific Popup. Практическое использование
Вызываем действие
$('.photogallery').magnificPopup({
delegate: 'a',
type: 'image',
closeOnContentClick: true,
image: {
verticalFit: false
},
gallery: {
enabled: true,
preload: [0,2],
navigateByImgClick: true,
arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
tPrev: 'Previous (Left arrow key)',
tNext: 'Next (Right arrow key)',
tCounter: '<span class="mfp-counter">%curr% of %total%</span>'
}
});
$('#gallery-carousel').magnificPopup({
type: 'image',
closeOnContentClick: true,
image: {
verticalFit: false
},
gallery: {
enabled: true,
preload: [0,2],
navigateByImgClick: true,
arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
tPrev: 'Previous (Left arrow key)',
tNext: 'Next (Right arrow key)',
tCounter: '<span class="mfp-counter">%curr% of %total%</span>'
}
});
$('.gallery').magnificPopup({
delegate: 'a',
type: 'image',
closeOnContentClick: true,
closeBtnInside: true,
mainClass: 'mfp-with-zoom mfp-img-mobile',
gallery: {
enabled: true
},
zoom: {
enabled: true,
duration: 300,
opener: function(element) {
return element.find('img');
}
}
});
// Группа изображений
var groups = {};
$('.galleryItem').each(function() {
var id = parseInt($(this).attr('data-group'), 10);
if(!groups[id]) {
groups[id] = [];
}
groups[id].push( this );
});
$.each(groups, function() {
$(this).magnificPopup({
type: 'image',
closeOnContentClick: true,
closeBtnInside: false,
gallery: { enabled:true }
})
});
Загружаем на сервер скрипт MagnificPopup.min.js
Magnific Popup - v1.1.0 - 2016-02-20
/*! Magnific Popup - v1.1.0 - 2016-02-20
* http://dimsemenov.com/plugins/magnific-popup/
* Copyright (c) 2016 Dmitry Semenov; */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):window.jQuery||window.Zepto)}(function(a){var b,c,d,e,f,g,h="Close",i="BeforeClose",j="AfterClose",k="BeforeAppend",l="MarkupParse",m="Open",n="Change",o="mfp",p="."+o,q="mfp-ready",r="mfp-removing",s="mfp-prevent-close",t=function(){},u=!!window.jQuery,v=a(window),w=function(a,c){b.ev.on(o+a+p,c)},x=function(b,c,d,e){var f=document.createElement("div");return f.className="mfp-"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},y=function(c,d){b.ev.triggerHandler(o+c,d),b.st.callbacks&&(c=c.charAt(0).toLowerCase()+c.slice(1),b.st.callbacks[c]&&b.st.callbacks[c].apply(b,a.isArray(d)?d:[d]))},z=function(c){return c===g&&b.currTemplate.closeBtn||(b.currTemplate.closeBtn=a(b.st.closeMarkup.replace("%title%",b.st.tClose)),g=c),b.currTemplate.closeBtn},A=function(){a.magnificPopup.instance||(b=new t,b.init(),a.magnificPopup.instance=b)},B=function(){var a=document.createElement("p").style,b=["ms","O","Moz","Webkit"];if(void 0!==a.transition)return!0;for(;b.length;)if(b.pop()+"Transition"in a)return!0;return!1};t.prototype={constructor:t,init:function(){var c=navigator.appVersion;b.isLowIE=b.isIE8=document.all&&!document.addEventListener,b.isAndroid=/android/gi.test(c),b.isIOS=/iphone|ipad|ipod/gi.test(c),b.supportsTransition=B(),b.probablyMobile=b.isAndroid||b.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),d=a(document),b.popupsCache={}},open:function(c){var e;if(c.isObj===!1){b.items=c.items.toArray(),b.index=0;var g,h=c.items;for(e=0;e<h.length;e++)if(g=h[e],g.parsed&&(g=g.el[0]),g===c.el[0]){b.index=e;break}}else b.items=a.isArray(c.items)?c.items:[c.items],b.index=c.index||0;if(b.isOpen)return void b.updateItemHTML();b.types=[],f="",c.mainEl&&c.mainEl.length?b.ev=c.mainEl.eq(0):b.ev=d,c.key?(b.popupsCache[c.key]||(b.popupsCache[c.key]={}),b.currTemplate=b.popupsCache[c.key]):b.currTemplate={},b.st=a.extend(!0,{},a.magnificPopup.defaults,c),b.fixedContentPos="auto"===b.st.fixedContentPos?!b.probablyMobile:b.st.fixedContentPos,b.st.modal&&(b.st.closeOnContentClick=!1,b.st.closeOnBgClick=!1,b.st.showCloseBtn=!1,b.st.enableEscapeKey=!1),b.bgOverlay||(b.bgOverlay=x("bg").on("click"+p,function(){b.close()}),b.wrap=x("wrap").attr("tabindex",-1).on("click"+p,function(a){b._checkIfClose(a.target)&&b.close()}),b.container=x("container",b.wrap)),b.contentContainer=x("content"),b.st.preloader&&(b.preloader=x("preloader",b.container,b.st.tLoading));var i=a.magnificPopup.modules;for(e=0;e<i.length;e++){var j=i[e];j=j.charAt(0).toUpperCase()+j.slice(1),b["init"+j].call(b)}y("BeforeOpen"),b.st.showCloseBtn&&(b.st.closeBtnInside?(w(l,function(a,b,c,d){c.close_replaceWith=z(d.type)}),f+=" mfp-close-btn-in"):b.wrap.append(z())),b.st.alignTop&&(f+=" mfp-align-top"),b.fixedContentPos?b.wrap.css({overflow:b.st.overflowY,overflowX:"hidden",overflowY:b.st.overflowY}):b.wrap.css({top:v.scrollTop(),position:"absolute"}),(b.st.fixedBgPos===!1||"auto"===b.st.fixedBgPos&&!b.fixedContentPos)&&b.bgOverlay.css({height:d.height(),position:"absolute"}),b.st.enableEscapeKey&&d.on("keyup"+p,function(a){27===a.keyCode&&b.close()}),v.on("resize"+p,function(){b.updateSize()}),b.st.closeOnContentClick||(f+=" mfp-auto-cursor"),f&&b.wrap.addClass(f);var k=b.wH=v.height(),n={};if(b.fixedContentPos&&b._hasScrollBar(k)){var o=b._getScrollbarSize();o&&(n.marginRight=o)}b.fixedContentPos&&(b.isIE7?a("body, html").css("overflow","hidden"):n.overflow="hidden");var r=b.st.mainClass;return b.isIE7&&(r+=" mfp-ie7"),r&&b._addClassToMFP(r),b.updateItemHTML(),y("BuildControls"),a("html").css(n),b.bgOverlay.add(b.wrap).prependTo(b.st.prependTo||a(document.body)),b._lastFocusedEl=document.activeElement,setTimeout(function(){b.content?(b._addClassToMFP(q),b._setFocus()):b.bgOverlay.addClass(q),d.on("focusin"+p,b._onFocusIn)},16),b.isOpen=!0,b.updateSize(k),y(m),c},close:function(){b.isOpen&&(y(i),b.isOpen=!1,b.st.removalDelay&&!b.isLowIE&&b.supportsTransition?(b._addClassToMFP(r),setTimeout(function(){b._close()},b.st.removalDelay)):b._close())},_close:function(){y(h);var c=r+" "+q+" ";if(b.bgOverlay.detach(),b.wrap.detach(),b.container.empty(),b.st.mainClass&&(c+=b.st.mainClass+" "),b._removeClassFromMFP(c),b.fixedContentPos){var e={marginRight:""};b.isIE7?a("body, html").css("overflow",""):e.overflow="",a("html").css(e)}d.off("keyup"+p+" focusin"+p),b.ev.off(p),b.wrap.attr("class","mfp-wrap").removeAttr("style"),b.bgOverlay.attr("class","mfp-bg"),b.container.attr("class","mfp-container"),!b.st.showCloseBtn||b.st.closeBtnInside&&b.currTemplate[b.currItem.type]!==!0||b.currTemplate.closeBtn&&b.currTemplate.closeBtn.detach(),b.st.autoFocusLast&&b._lastFocusedEl&&a(b._lastFocusedEl).focus(),b.currItem=null,b.content=null,b.currTemplate=null,b.prevHeight=0,y(j)},updateSize:function(a){if(b.isIOS){var c=document.documentElement.clientWidth/window.innerWidth,d=window.innerHeight*c;b.wrap.css("height",d),b.wH=d}else b.wH=a||v.height();b.fixedContentPos||b.wrap.css("height",b.wH),y("Resize")},updateItemHTML:function(){var c=b.items[b.index];b.contentContainer.detach(),b.content&&b.content.detach(),c.parsed||(c=b.parseEl(b.index));var d=c.type;if(y("BeforeChange",[b.currItem?b.currItem.type:"",d]),b.currItem=c,!b.currTemplate[d]){var f=b.st[d]?b.st[d].markup:!1;y("FirstMarkupParse",f),f?b.currTemplate[d]=a(f):b.currTemplate[d]=!0}e&&e!==c.type&&b.container.removeClass("mfp-"+e+"-holder");var g=b["get"+d.charAt(0).toUpperCase()+d.slice(1)](c,b.currTemplate[d]);b.appendContent(g,d),c.preloaded=!0,y(n,c),e=c.type,b.container.prepend(b.contentContainer),y("AfterChange")},appendContent:function(a,c){b.content=a,a?b.st.showCloseBtn&&b.st.closeBtnInside&&b.currTemplate[c]===!0?b.content.find(".mfp-close").length||b.content.append(z()):b.content=a:b.content="",y(k),b.container.addClass("mfp-"+c+"-holder"),b.contentContainer.append(b.content)},parseEl:function(c){var d,e=b.items[c];if(e.tagName?e={el:a(e)}:(d=e.type,e={data:e,src:e.src}),e.el){for(var f=b.types,g=0;g<f.length;g++)if(e.el.hasClass("mfp-"+f[g])){d=f[g];break}e.src=e.el.attr("data-mfp-src"),e.src||(e.src=e.el.attr("href"))}return e.type=d||b.st.type||"inline",e.index=c,e.parsed=!0,b.items[c]=e,y("ElementParse",e),b.items[c]},addGroup:function(a,c){var d=function(d){d.mfpEl=this,b._openClick(d,a,c)};c||(c={});var e="click.magnificPopup";c.mainEl=a,c.items?(c.isObj=!0,a.off(e).on(e,d)):(c.isObj=!1,c.delegate?a.off(e).on(e,c.delegate,d):(c.items=a,a.off(e).on(e,d)))},_openClick:function(c,d,e){var f=void 0!==e.midClick?e.midClick:a.magnificPopup.defaults.midClick;if(f||!(2===c.which||c.ctrlKey||c.metaKey||c.altKey||c.shiftKey)){var g=void 0!==e.disableOn?e.disableOn:a.magnificPopup.defaults.disableOn;if(g)if(a.isFunction(g)){if(!g.call(b))return!0}else if(v.width()<g)return!0;c.type&&(c.preventDefault(),b.isOpen&&c.stopPropagation()),e.el=a(c.mfpEl),e.delegate&&(e.items=d.find(e.delegate)),b.open(e)}},updateStatus:function(a,d){if(b.preloader){c!==a&&b.container.removeClass("mfp-s-"+c),d||"loading"!==a||(d=b.st.tLoading);var e={status:a,text:d};y("UpdateStatus",e),a=e.status,d=e.text,b.preloader.html(d),b.preloader.find("a").on("click",function(a){a.stopImmediatePropagation()}),b.container.addClass("mfp-s-"+a),c=a}},_checkIfClose:function(c){if(!a(c).hasClass(s)){var d=b.st.closeOnContentClick,e=b.st.closeOnBgClick;if(d&&e)return!0;if(!b.content||a(c).hasClass("mfp-close")||b.preloader&&c===b.preloader[0])return!0;if(c===b.content[0]||a.contains(b.content[0],c)){if(d)return!0}else if(e&&a.contains(document,c))return!0;return!1}},_addClassToMFP:function(a){b.bgOverlay.addClass(a),b.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),b.wrap.removeClass(a)},_hasScrollBar:function(a){return(b.isIE7?d.height():document.body.scrollHeight)>(a||v.height())},_setFocus:function(){(b.st.focus?b.content.find(b.st.focus).eq(0):b.wrap).focus()},_onFocusIn:function(c){return c.target===b.wrap[0]||a.contains(b.wrap[0],c.target)?void 0:(b._setFocus(),!1)},_parseMarkup:function(b,c,d){var e;d.data&&(c=a.extend(d.data,c)),y(l,[b,c,d]),a.each(c,function(c,d){if(void 0===d||d===!1)return!0;if(e=c.split("_"),e.length>1){var f=b.find(p+"-"+e[0]);if(f.length>0){var g=e[1];"replaceWith"===g?f[0]!==d[0]&&f.replaceWith(d):"img"===g?f.is("img")?f.attr("src",d):f.replaceWith(a("<img>").attr("src",d).attr("class",f.attr("class"))):f.attr(e[1],d)}}else b.find(p+"-"+c).html(d)})},_getScrollbarSize:function(){if(void 0===b.scrollbarSize){var a=document.createElement("div");a.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(a),b.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return b.scrollbarSize}},a.magnificPopup={instance:null,proto:t.prototype,modules:[],open:function(b,c){return A(),b=b?a.extend(!0,{},b):{},b.isObj=!0,b.index=c||0,this.instance.open(b)},close:function(){return a.magnificPopup.instance&&a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">×</button>',tClose:"Close (Esc)",tLoading:"Loading...",autoFocusLast:!0}},a.fn.magnificPopup=function(c){A();var d=a(this);if("string"==typeof c)if("open"===c){var e,f=u?d.data("magnificPopup"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1));else c=a.extend(!0,{},c),u?d.data("magnificPopup",c):d[0].magnificPopup=c,b.addGroup(d,c);return d};var C,D,E,F="inline",G=function(){E&&(D.after(E.addClass(C)).detach(),E=null)};a.magnificPopup.registerModule(F,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){b.types.push(F),w(h+"."+F,function(){G()})},getInline:function(c,d){if(G(),c.src){var e=b.st.inline,f=a(c.src);if(f.length){var g=f[0].parentNode;g&&g.tagName&&(D||(C=e.hiddenClass,D=x(C),C="mfp-"+C),E=f.after(D).detach().removeClass(C)),b.updateStatus("ready")}else b.updateStatus("error",e.tNotFound),f=a("<div>");return c.inlineElement=f,f}return b.updateStatus("ready"),b._parseMarkup(d,{},c),d}}});var H,I="ajax",J=function(){H&&a(document.body).removeClass(H)},K=function(){J(),b.req&&b.req.abort()};a.magnificPopup.registerModule(I,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a href="%url%">The content</a> could not be loaded.'},proto:{initAjax:function(){b.types.push(I),H=b.st.ajax.cursor,w(h+"."+I,K),w("BeforeChange."+I,K)},getAjax:function(c){H&&a(document.body).addClass(H),b.updateStatus("loading");var d=a.extend({url:c.src,success:function(d,e,f){var g={data:d,xhr:f};y("ParseAjax",g),b.appendContent(a(g.data),I),c.finished=!0,J(),b._setFocus(),setTimeout(function(){b.wrap.addClass(q)},16),b.updateStatus("ready"),y("AjaxContentAdded")},error:function(){J(),c.finished=c.loadError=!0,b.updateStatus("error",b.st.ajax.tError.replace("%url%",c.src))}},b.st.ajax.settings);return b.req=a.ajax(d),""}}});var L,M=function(c){if(c.data&&void 0!==c.data.title)return c.data.title;var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return d.call(b,c);if(c.el)return c.el.attr(d)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><figure><div class="mfp-img"></div><figcaption><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var c=b.st.image,d=".image";b.types.push("image"),w(m+d,function(){"image"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),w(h+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),v.off("resize"+p)}),w("Resize"+d,b.resizeImage),b.isLowIE&&w("AfterChange",b.resizeImage)},resizeImage:function(){var a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var c=0;b.isLowIE&&(c=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,L&&clearInterval(L),a.isCheckingImgSize=!1,y("ImageHasSize",a),a.imgHidden&&(b.content&&b.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var c=0,d=a.img[0],e=function(f){L&&clearInterval(L),L=setInterval(function(){return d.naturalWidth>0?void b._onImageHasSize(a):(c>200&&clearInterval(L),c++,void(3===c?e(10):40===c?e(50):100===c&&e(500)))},f)};e(1)},getImage:function(c,d){var e=0,f=function(){c&&(c.img[0].complete?(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("ready")),c.hasSize=!0,c.loaded=!0,y("ImageLoadComplete")):(e++,200>e?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("error",h.tError.replace("%url%",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(".mfp-img");if(i.length){var j=document.createElement("img");j.className="mfp-img",c.el&&c.el.find("img").length&&(j.alt=c.el.find("img").attr("alt")),c.img=a(j).on("load.mfploader",f).on("error.mfploader",g),j.src=c.src,i.is("img")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return b._parseMarkup(d,{title:M(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(L&&clearInterval(L),c.loadError?(d.addClass("mfp-loading"),b.updateStatus("error",h.tError.replace("%url%",c.src))):(d.removeClass("mfp-loading"),b.updateStatus("ready")),d):(b.updateStatus("loading"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass("mfp-loading"),b.findImageSize(c)),d)}}});var N,O=function(){return void 0===N&&(N=void 0!==document.createElement("p").style.MozTransform),N};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var a,c=b.st.zoom,d=".zoom";if(c.enabled&&b.supportsTransition){var e,f,g=c.duration,j=function(a){var b=a.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all "+c.duration/1e3+"s "+c.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,b.css(e),b},k=function(){b.content.css("visibility","visible")};w("BuildControls"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css("visibility","hidden"),a=b._getItemToZoom(),!a)return void k();f=j(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){k(),setTimeout(function(){f.remove(),a=f=null,y("ZoomAnimationEnded")},16)},g)},16)}}),w(i+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(a=b._getItemToZoom(),!a)return;f=j(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css("visibility","hidden"),setTimeout(function(){f.css(b._getOffset())},16)}}),w(h+d,function(){b._allowZoom()&&(k(),f&&f.remove(),a=null)})}},_allowZoom:function(){return"image"===b.currItem.type},_getItemToZoom:function(){return b.currItem.hasSize?b.currItem.img:!1},_getOffset:function(c){var d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var e=d.offset(),f=parseInt(d.css("padding-top"),10),g=parseInt(d.css("padding-bottom"),10);e.top-=a(window).scrollTop()-f;var h={width:d.width(),height:(u?d.innerHeight():d[0].offsetHeight)-g-f};return O()?h["-moz-transform"]=h.transform="translate("+e.left+"px,"+e.top+"px)":(h.left=e.left,h.top=e.top),h}}});var P="iframe",Q="//about:blank",R=function(a){if(b.currTemplate[P]){var c=b.currTemplate[P].find("iframe");c.length&&(a||(c[0].src=Q),b.isIE8&&c.css("display",a?"block":"none"))}};a.magnificPopup.registerModule(P,{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){b.types.push(P),w("BeforeChange",function(a,b,c){b!==c&&(b===P?R():c===P&&R(!0))}),w(h+"."+P,function(){R()})},getIframe:function(c,d){var e=c.src,f=b.st.iframe;a.each(f.patterns,function(){return e.indexOf(this.index)>-1?(this.id&&(e="string"==typeof this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace("%id%",e),!1):void 0});var g={};return f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus("ready"),d}}});var S=function(a){var c=b.items.length;return a>c-1?a-c:0>a?c+a:a},T=function(a,b,c){return a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var c=b.st.gallery,e=".mfp-gallery";return b.direction=!0,c&&c.enabled?(f+=" mfp-gallery",w(m+e,function(){c.navigateByImgClick&&b.wrap.on("click"+e,".mfp-img",function(){return b.items.length>1?(b.next(),!1):void 0}),d.on("keydown"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),w("UpdateStatus"+e,function(a,c){c.text&&(c.text=T(c.text,b.currItem.index,b.items.length))}),w(l+e,function(a,d,e,f){var g=b.items.length;e.counter=g>1?T(c.tCounter,f.index,g):""}),w("BuildControls"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,"left")).addClass(s),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,"right")).addClass(s);e.click(function(){b.prev()}),f.click(function(){b.next()}),b.container.append(e.add(f))}}),w(n+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),void w(h+e,function(){d.off(e),b.wrap.off("click"+e),b.arrowRight=b.arrowLeft=null})):!1},next:function(){b.direction=!0,b.index=S(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=S(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=S(c),!b.items[c].preloaded){var d=b.items[c];d.parsed||(d=b.parseEl(c)),y("LazyLoad",d),"image"===d.type&&(d.img=a('<img class="mfp-img" />').on("load.mfploader",function(){d.hasSize=!0}).on("error.mfploader",function(){d.hasSize=!0,d.loadError=!0,y("LazyLoadError",d)}).attr("src",d.src)),d.preloaded=!0}}}});var U="retina";a.magnificPopup.registerModule(U,{options:{replaceSrc:function(a){return a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(w("ImageHasSize."+U,function(a,b){b.img.css({"max-width":b.img[0].naturalWidth/c,width:"100%"})}),w("ElementParse."+U,function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),A()});