diff --git a/CHANGELOG.md b/CHANGELOG.md index 8150e29..8834ead 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### 0.2.0-beta.5 +- Added compatibility with Flarum 0.1.0-beta.14 + ### 0.2.0-beta.4 - **Fix** captions were not working when you define them in URL BBCodes. - Give the `button` role to empty anchor tags for the sake of semantics. diff --git a/README.md b/README.md index 5e4ea13..7553e6d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # fancyBox Extension for Flarum -[![GPLv3 license](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://github.com/the-turk/flarum-ext-fancybox/blob/master/LICENSE) [![Latest Stable Version](https://img.shields.io/packagist/v/the-turk/flarum-ext-fancybox.svg)](https://packagist.org/packages/the-turk/flarum-ext-fancybox) [![Total Downloads](https://img.shields.io/packagist/dt/the-turk/flarum-ext-fancybox.svg)](https://packagist.org/packages/the-turk/flarum-ext-fancybox) +[![GPLv3 license](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://github.com/malago/flarum-ext-fancybox/blob/master/LICENSE) [![Latest Stable Version](https://img.shields.io/packagist/v/malago/flarum-ext-fancybox.svg)](https://packagist.org/packages/malago/flarum-ext-fancybox) [![Total Downloads](https://img.shields.io/packagist/dt/malago/flarum-ext-fancybox.svg)](https://packagist.org/packages/malago/flarum-ext-fancybox) -**Disclaimer:** This extension has forked from `squeevee/flarum-ext-fancybox` +**Disclaimer:** This extension has forked from `the-turk/flarum-ext-fancybox` ![fancyBox](https://i.ibb.co/kBWDJSL/fancyBox.png) @@ -18,19 +18,19 @@ ## Conflictions -- This package conflicts with `squeevee/flarum-ext-fancybox`, so you need to remove it first. +- This package conflicts with `squeevee/flarum-ext-fancybox` and `the-turk/flarum-ext-fancybox`, so you need to remove them first. - It seems like this package is not compatible with `reflar/recache` (see [#4](https://github.com/squeevee/flarum-ext-fancybox/issues/4)). ## Installation ```bash -composer require the-turk/flarum-ext-fancybox +composer require malago/flarum-ext-fancybox ``` ## Updating ```bash -composer update the-turk/flarum-ext-fancybox +composer update malago/flarum-ext-fancybox php flarum cache:clear ``` @@ -87,6 +87,6 @@ You need to have the `flarum/bbcode` extension in order to add captions. The `ti ## Links - [Flarum Discuss post](https://discuss.flarum.org/d/19535-fancybox-extension-beta) -- [Source code on GitHub](https://github.com/the-turk/flarum-ext-fancybox) -- [Changelog](https://github.com/the-turk/flarum-ext-fancybox/blob/master/CHANGELOG.md) -- [Download via Packagist](https://packagist.org/packages/the-turk/flarum-ext-fancybox) +- [Source code on GitHub](https://github.com/malago86/flarum-ext-fancybox) +- [Changelog](https://github.com/malago86/flarum-ext-fancybox/blob/master/CHANGELOG.md) +- [Download via Packagist](https://packagist.org/packages/malago/flarum-ext-fancybox) diff --git a/composer.json b/composer.json index 0a964e1..bf79f1f 100644 --- a/composer.json +++ b/composer.json @@ -1,41 +1,49 @@ -{ - "name": "the-turk/flarum-ext-fancybox", - "description": "Image formatting and lightbox modal using fancyBox (forked from squeevee's).", - "type": "flarum-extension", - "require": { - "flarum/core": "^0.1.0-beta.8" - }, - "conflict": { - "squeevee/flarum-ext-fancybox": ">=0.1-beta" - }, - "license": "GPL-3.0-or-later", - "authors": [ - { - "name": "Ellie Hawk", - "email": "squeevee@yahoo.com" - }, - { - "name": "Hasan Özbey", - "email": "hasanoozbey@gmail.com" - } - ], - "support": { - "issues": "https://github.com/the-turk/flarum-ext-fancybox/issues", - "source": "https://github.com/the-turk/flarum-ext-fancybox" - }, - "extra": { - "flarum-extension": { - "title": "FancyBox", - "icon": { - "name": "far fa-image", - "backgroundColor": "#b72a2a", - "color": "#fff" - } - } - }, - "autoload": { - "psr-4": { - "TheTurk\\FancyBox\\": "src/" - } - } -} +{ + "name": "malago/flarum-ext-fancybox", + "description": "Image formatting and lightbox modal using fancyBox (original from the-turk and squeevee).", + "keywords": [ + "flarum" + ], + "conflict": + { + "the-turk/flarum-ext-fancybox": ">=0.1-beta", + "squeevee/flarum-ext-fancybox": ">=0.1-beta" + }, + "type": "flarum-extension", + "license": "GPL-3.0-or-later", + "require": { + "flarum/core": "^0.1.0-beta.14" + }, + "authors": [ + { + "name": "Ellie Hawk", + "email": "squeevee@yahoo.com" + }, + { + "name": "Hasan Özbey", + "email": "hasanoozbey@gmail.com" + } + ], + "autoload": { + "psr-4": { + "Malago\\FancyBox\\": "src/" + } + }, + "extra": { + "flarum-extension": { + "title": "FancyBox", + "icon": { + "name": "far fa-image", + "backgroundColor": "#b72a2a", + "color": "#fff" + } + }, + "flagrow": { + "discuss": "https://discuss.flarum.org/d/19535-fancybox-extension-beta" + }, + "support": { + "issues": "https://github.com/malago86/flarum-ext-fancybox/issues", + "source": "https://github.com/malago86/flarum-ext-fancybox" + } + } +} diff --git a/extend.php b/extend.php index 7b86683..ade52a2 100644 --- a/extend.php +++ b/extend.php @@ -14,7 +14,7 @@ * GNU General Public License for more details. */ -namespace TheTurk\FancyBox; +namespace Malago\FancyBox; use Flarum\Extend; use Illuminate\Contracts\Events\Dispatcher; diff --git a/js/dist/forum.js b/js/dist/forum.js index 8bee900..18f3168 100644 --- a/js/dist/forum.js +++ b/js/dist/forum.js @@ -1,5939 +1,2 @@ -module.exports = -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./forum.js"); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./forum.js": -/*!******************!*\ - !*** ./forum.js ***! - \******************/ -/*! no exports provided */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _src_forum__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/forum */ "./src/forum/index.js"); -/* empty/unused harmony star reexport */ - -/***/ }), - -/***/ "./node_modules/@fancyapps/fancybox/dist/jquery.fancybox.js": -/*!******************************************************************!*\ - !*** ./node_modules/@fancyapps/fancybox/dist/jquery.fancybox.js ***! - \******************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -// ================================================== -// fancyBox v3.5.7 -// -// Licensed GPLv3 for open source use -// or fancyBox Commercial License for commercial use -// -// http://fancyapps.com/fancybox/ -// Copyright 2019 fancyApps -// -// ================================================== -(function (window, document, $, undefined) { - "use strict"; - - window.console = window.console || { - info: function (stuff) {} - }; - - // If there's no jQuery, fancyBox can't work - // ========================================= - - if (!$) { - return; - } - - // Check if fancyBox is already initialized - // ======================================== - - if ($.fn.fancybox) { - console.info("fancyBox already initialized"); - - return; - } - - // Private default settings - // ======================== - - var defaults = { - // Close existing modals - // Set this to false if you do not need to stack multiple instances - closeExisting: false, - - // Enable infinite gallery navigation - loop: false, - - // Horizontal space between slides - gutter: 50, - - // Enable keyboard navigation - keyboard: true, - - // Should allow caption to overlap the content - preventCaptionOverlap: true, - - // Should display navigation arrows at the screen edges - arrows: true, - - // Should display counter at the top left corner - infobar: true, - - // Should display close button (using `btnTpl.smallBtn` template) over the content - // Can be true, false, "auto" - // If "auto" - will be automatically enabled for "html", "inline" or "ajax" items - smallBtn: "auto", - - // Should display toolbar (buttons at the top) - // Can be true, false, "auto" - // If "auto" - will be automatically hidden if "smallBtn" is enabled - toolbar: "auto", - - // What buttons should appear in the top right corner. - // Buttons will be created using templates from `btnTpl` option - // and they will be placed into toolbar (class="fancybox-toolbar"` element) - buttons: [ - "zoom", - //"share", - "slideShow", - //"fullScreen", - //"download", - "thumbs", - "close" - ], - - // Detect "idle" time in seconds - idleTime: 3, - - // Disable right-click and use simple image protection for images - protect: false, - - // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc - modal: false, - - image: { - // Wait for images to load before displaying - // true - wait for image to load and then display; - // false - display thumbnail and load the full-sized image over top, - // requires predefined image dimensions (`data-width` and `data-height` attributes) - preload: false - }, - - ajax: { - // Object containing settings for ajax request - settings: { - // This helps to indicate that request comes from the modal - // Feel free to change naming - data: { - fancybox: true - } - } - }, - - iframe: { - // Iframe template - tpl: '', - - // Preload iframe before displaying it - // This allows to calculate iframe content width and height - // (note: Due to "Same Origin Policy", you can't get cross domain data). - preload: true, - - // Custom CSS styling for iframe wrapping element - // You can use this to set custom iframe dimensions - css: {}, - - // Iframe tag attributes - attr: { - scrolling: "auto" - } - }, - - // For HTML5 video only - video: { - tpl: '", - format: "", // custom video format - autoStart: true - }, - - // Default content type if cannot be detected automatically - defaultType: "image", - - // Open/close animation type - // Possible values: - // false - disable - // "zoom" - zoom images from/to thumbnail - // "fade" - // "zoom-in-out" - // - animationEffect: "zoom", - - // Duration in ms for open/close animation - animationDuration: 366, - - // Should image change opacity while zooming - // If opacity is "auto", then opacity will be changed if image and thumbnail have different aspect ratios - zoomOpacity: "auto", - - // Transition effect between slides - // - // Possible values: - // false - disable - // "fade' - // "slide' - // "circular' - // "tube' - // "zoom-in-out' - // "rotate' - // - transitionEffect: "fade", - - // Duration in ms for transition animation - transitionDuration: 366, - - // Custom CSS class for slide element - slideClass: "", - - // Custom CSS class for layout - baseClass: "", - - // Base template for layout - baseTpl: '", - - // Loading indicator template - spinnerTpl: '
', - - // Error message template - errorTpl: '

{{ERROR}}

', - - btnTpl: { - download: '' + - '' + - "", - - zoom: '", - - close: '", - - // Arrows - arrowLeft: '", - - arrowRight: '", - - // This small close button will be appended to your html/inline/ajax content by default, - // if "smallBtn" option is not set to false - smallBtn: '" - }, - - // Container is injected into this element - parentEl: "body", - - // Hide browser vertical scrollbars; use at your own risk - hideScrollbar: true, - - // Focus handling - // ============== - - // Try to focus on the first focusable element after opening - autoFocus: true, - - // Put focus back to active element after closing - backFocus: true, - - // Do not let user to focus on element outside modal content - trapFocus: true, - - // Module specific options - // ======================= - - fullScreen: { - autoStart: false - }, - - // Set `touch: false` to disable panning/swiping - touch: { - vertical: true, // Allow to drag content vertically - momentum: true // Continue movement after releasing mouse/touch when panning - }, - - // Hash value when initializing manually, - // set `false` to disable hash change - hash: null, - - // Customize or add new media types - // Example: - /* - media : { - youtube : { - params : { - autoplay : 0 - } - } - } - */ - media: {}, - - slideShow: { - autoStart: false, - speed: 3000 - }, - - thumbs: { - autoStart: false, // Display thumbnails on opening - hideOnClose: true, // Hide thumbnail grid when closing animation starts - parentEl: ".fancybox-container", // Container is injected into this element - axis: "y" // Vertical (y) or horizontal (x) scrolling - }, - - // Use mousewheel to navigate gallery - // If 'auto' - enabled for images only - wheel: "auto", - - // Callbacks - //========== - - // See Documentation/API/Events for more information - // Example: - /* - afterShow: function( instance, current ) { - console.info( 'Clicked element:' ); - console.info( current.opts.$orig ); - } - */ - - onInit: $.noop, // When instance has been initialized - - beforeLoad: $.noop, // Before the content of a slide is being loaded - afterLoad: $.noop, // When the content of a slide is done loading - - beforeShow: $.noop, // Before open animation starts - afterShow: $.noop, // When content is done loading and animating - - beforeClose: $.noop, // Before the instance attempts to close. Return false to cancel the close. - afterClose: $.noop, // After instance has been closed - - onActivate: $.noop, // When instance is brought to front - onDeactivate: $.noop, // When other instance has been activated - - // Interaction - // =========== - - // Use options below to customize taken action when user clicks or double clicks on the fancyBox area, - // each option can be string or method that returns value. - // - // Possible values: - // "close" - close instance - // "next" - move to next gallery item - // "nextOrClose" - move to next gallery item or close if gallery has only one item - // "toggleControls" - show/hide controls - // "zoom" - zoom image (if loaded) - // false - do nothing - - // Clicked on the content - clickContent: function (current, event) { - return current.type === "image" ? "zoom" : false; - }, - - // Clicked on the slide - clickSlide: "close", - - // Clicked on the background (backdrop) element; - // if you have not changed the layout, then most likely you need to use `clickSlide` option - clickOutside: "close", - - // Same as previous two, but for double click - dblclickContent: false, - dblclickSlide: false, - dblclickOutside: false, - - // Custom options when mobile device is detected - // ============================================= - - mobile: { - preventCaptionOverlap: false, - idleTime: false, - clickContent: function (current, event) { - return current.type === "image" ? "toggleControls" : false; - }, - clickSlide: function (current, event) { - return current.type === "image" ? "toggleControls" : "close"; - }, - dblclickContent: function (current, event) { - return current.type === "image" ? "zoom" : false; - }, - dblclickSlide: function (current, event) { - return current.type === "image" ? "zoom" : false; - } - }, - - // Internationalization - // ==================== - - lang: "en", - i18n: { - en: { - CLOSE: "Close", - NEXT: "Next", - PREV: "Previous", - ERROR: "The requested content cannot be loaded.
Please try again later.", - PLAY_START: "Start slideshow", - PLAY_STOP: "Pause slideshow", - FULL_SCREEN: "Full screen", - THUMBS: "Thumbnails", - DOWNLOAD: "Download", - SHARE: "Share", - ZOOM: "Zoom" - }, - de: { - CLOSE: "Schließen", - NEXT: "Weiter", - PREV: "Zurück", - ERROR: "Die angeforderten Daten konnten nicht geladen werden.
Bitte versuchen Sie es später nochmal.", - PLAY_START: "Diaschau starten", - PLAY_STOP: "Diaschau beenden", - FULL_SCREEN: "Vollbild", - THUMBS: "Vorschaubilder", - DOWNLOAD: "Herunterladen", - SHARE: "Teilen", - ZOOM: "Vergrößern" - } - } - }; - - // Few useful variables and methods - // ================================ - - var $W = $(window); - var $D = $(document); - - var called = 0; - - // Check if an object is a jQuery object and not a native JavaScript object - // ======================================================================== - var isQuery = function (obj) { - return obj && obj.hasOwnProperty && obj instanceof $; - }; - - // Handle multiple browsers for "requestAnimationFrame" and "cancelAnimationFrame" - // =============================================================================== - var requestAFrame = (function () { - return ( - window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - // if all else fails, use setTimeout - function (callback) { - return window.setTimeout(callback, 1000 / 60); - } - ); - })(); - - var cancelAFrame = (function () { - return ( - window.cancelAnimationFrame || - window.webkitCancelAnimationFrame || - window.mozCancelAnimationFrame || - window.oCancelAnimationFrame || - function (id) { - window.clearTimeout(id); - } - ); - })(); - - // Detect the supported transition-end event property name - // ======================================================= - var transitionEnd = (function () { - var el = document.createElement("fakeelement"), - t; - - var transitions = { - transition: "transitionend", - OTransition: "oTransitionEnd", - MozTransition: "transitionend", - WebkitTransition: "webkitTransitionEnd" - }; - - for (t in transitions) { - if (el.style[t] !== undefined) { - return transitions[t]; - } - } - - return "transitionend"; - })(); - - // Force redraw on an element. - // This helps in cases where the browser doesn't redraw an updated element properly - // ================================================================================ - var forceRedraw = function ($el) { - return $el && $el.length && $el[0].offsetHeight; - }; - - // Exclude array (`buttons`) options from deep merging - // =================================================== - var mergeOpts = function (opts1, opts2) { - var rez = $.extend(true, {}, opts1, opts2); - - $.each(opts2, function (key, value) { - if ($.isArray(value)) { - rez[key] = value; - } - }); - - return rez; - }; - - // How much of an element is visible in viewport - // ============================================= - - var inViewport = function (elem) { - var elemCenter, rez; - - if (!elem || elem.ownerDocument !== document) { - return false; - } - - $(".fancybox-container").css("pointer-events", "none"); - - elemCenter = { - x: elem.getBoundingClientRect().left + elem.offsetWidth / 2, - y: elem.getBoundingClientRect().top + elem.offsetHeight / 2 - }; - - rez = document.elementFromPoint(elemCenter.x, elemCenter.y) === elem; - - $(".fancybox-container").css("pointer-events", ""); - - return rez; - }; - - // Class definition - // ================ - - var FancyBox = function (content, opts, index) { - var self = this; - - self.opts = mergeOpts({ - index: index - }, $.fancybox.defaults); - - if ($.isPlainObject(opts)) { - self.opts = mergeOpts(self.opts, opts); - } - - if ($.fancybox.isMobile) { - self.opts = mergeOpts(self.opts, self.opts.mobile); - } - - self.id = self.opts.id || ++called; - - self.currIndex = parseInt(self.opts.index, 10) || 0; - self.prevIndex = null; - - self.prevPos = null; - self.currPos = 0; - - self.firstRun = true; - - // All group items - self.group = []; - - // Existing slides (for current, next and previous gallery items) - self.slides = {}; - - // Create group elements - self.addContent(content); - - if (!self.group.length) { - return; - } - - self.init(); - }; - - $.extend(FancyBox.prototype, { - // Create DOM structure - // ==================== - - init: function () { - var self = this, - firstItem = self.group[self.currIndex], - firstItemOpts = firstItem.opts, - $container, - buttonStr; - - if (firstItemOpts.closeExisting) { - $.fancybox.close(true); - } - - // Hide scrollbars - // =============== - - $("body").addClass("fancybox-active"); - - if ( - !$.fancybox.getInstance() && - firstItemOpts.hideScrollbar !== false && - !$.fancybox.isMobile && - document.body.scrollHeight > window.innerHeight - ) { - $("head").append( - '" - ); - - $("body").addClass("compensate-for-scrollbar"); - } - - // Build html markup and set references - // ==================================== - - // Build html code for buttons and insert into main template - buttonStr = ""; - - $.each(firstItemOpts.buttons, function (index, value) { - buttonStr += firstItemOpts.btnTpl[value] || ""; - }); - - // Create markup from base template, it will be initially hidden to - // avoid unnecessary work like painting while initializing is not complete - $container = $( - self.translate( - self, - firstItemOpts.baseTpl - .replace("{{buttons}}", buttonStr) - .replace("{{arrows}}", firstItemOpts.btnTpl.arrowLeft + firstItemOpts.btnTpl.arrowRight) - ) - ) - .attr("id", "fancybox-container-" + self.id) - .addClass(firstItemOpts.baseClass) - .data("FancyBox", self) - .appendTo(firstItemOpts.parentEl); - - // Create object holding references to jQuery wrapped nodes - self.$refs = { - container: $container - }; - - ["bg", "inner", "infobar", "toolbar", "stage", "caption", "navigation"].forEach(function (item) { - self.$refs[item] = $container.find(".fancybox-" + item); - }); - - self.trigger("onInit"); - - // Enable events, deactive previous instances - self.activate(); - - // Build slides, load and reveal content - self.jumpTo(self.currIndex); - }, - - // Simple i18n support - replaces object keys found in template - // with corresponding values - // ============================================================ - - translate: function (obj, str) { - var arr = obj.opts.i18n[obj.opts.lang] || obj.opts.i18n.en; - - return str.replace(/\{\{(\w+)\}\}/g, function (match, n) { - return arr[n] === undefined ? match : arr[n]; - }); - }, - - // Populate current group with fresh content - // Check if each object has valid type and content - // =============================================== - - addContent: function (content) { - var self = this, - items = $.makeArray(content), - thumbs; - - $.each(items, function (i, item) { - var obj = {}, - opts = {}, - $item, - type, - found, - src, - srcParts; - - // Step 1 - Make sure we have an object - // ==================================== - - if ($.isPlainObject(item)) { - // We probably have manual usage here, something like - // $.fancybox.open( [ { src : "image.jpg", type : "image" } ] ) - - obj = item; - opts = item.opts || item; - } else if ($.type(item) === "object" && $(item).length) { - // Here we probably have jQuery collection returned by some selector - $item = $(item); - - // Support attributes like `data-options='{"touch" : false}'` and `data-touch='false'` - opts = $item.data() || {}; - opts = $.extend(true, {}, opts, opts.options); - - // Here we store clicked element - opts.$orig = $item; - - obj.src = self.opts.src || opts.src || $item.attr("href"); - - // Assume that simple syntax is used, for example: - // `$.fancybox.open( $("#test"), {} );` - if (!obj.type && !obj.src) { - obj.type = "inline"; - obj.src = item; - } - } else { - // Assume we have a simple html code, for example: - // $.fancybox.open( '

Hi!

' ); - obj = { - type: "html", - src: item + "" - }; - } - - // Each gallery object has full collection of options - obj.opts = $.extend(true, {}, self.opts, opts); - - // Do not merge buttons array - if ($.isArray(opts.buttons)) { - obj.opts.buttons = opts.buttons; - } - - if ($.fancybox.isMobile && obj.opts.mobile) { - obj.opts = mergeOpts(obj.opts, obj.opts.mobile); - } - - // Step 2 - Make sure we have content type, if not - try to guess - // ============================================================== - - type = obj.type || obj.opts.type; - src = obj.src || ""; - - if (!type && src) { - if ((found = src.match(/\.(mp4|mov|ogv|webm)((\?|#).*)?$/i))) { - type = "video"; - - if (!obj.opts.video.format) { - obj.opts.video.format = "video/" + (found[1] === "ogv" ? "ogg" : found[1]); - } - } else if (src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i)) { - type = "image"; - } else if (src.match(/\.(pdf)((\?|#).*)?$/i)) { - type = "iframe"; - obj = $.extend(true, obj, { - contentType: "pdf", - opts: { - iframe: { - preload: false - } - } - }); - } else if (src.charAt(0) === "#") { - type = "inline"; - } - } - - if (type) { - obj.type = type; - } else { - self.trigger("objectNeedsType", obj); - } - - if (!obj.contentType) { - obj.contentType = $.inArray(obj.type, ["html", "inline", "ajax"]) > -1 ? "html" : obj.type; - } - - // Step 3 - Some adjustments - // ========================= - - obj.index = self.group.length; - - if (obj.opts.smallBtn == "auto") { - obj.opts.smallBtn = $.inArray(obj.type, ["html", "inline", "ajax"]) > -1; - } - - if (obj.opts.toolbar === "auto") { - obj.opts.toolbar = !obj.opts.smallBtn; - } - - // Find thumbnail image, check if exists and if is in the viewport - obj.$thumb = obj.opts.$thumb || null; - - if (obj.opts.$trigger && obj.index === self.opts.index) { - obj.$thumb = obj.opts.$trigger.find("img:first"); - - if (obj.$thumb.length) { - obj.opts.$orig = obj.opts.$trigger; - } - } - - if (!(obj.$thumb && obj.$thumb.length) && obj.opts.$orig) { - obj.$thumb = obj.opts.$orig.find("img:first"); - } - - if (obj.$thumb && !obj.$thumb.length) { - obj.$thumb = null; - } - - obj.thumb = obj.opts.thumb || (obj.$thumb ? obj.$thumb[0].src : null); - - // "caption" is a "special" option, it can be used to customize caption per gallery item - if ($.type(obj.opts.caption) === "function") { - obj.opts.caption = obj.opts.caption.apply(item, [self, obj]); - } - - if ($.type(self.opts.caption) === "function") { - obj.opts.caption = self.opts.caption.apply(item, [self, obj]); - } - - // Make sure we have caption as a string or jQuery object - if (!(obj.opts.caption instanceof $)) { - obj.opts.caption = obj.opts.caption === undefined ? "" : obj.opts.caption + ""; - } - - // Check if url contains "filter" used to filter the content - // Example: "ajax.html #something" - if (obj.type === "ajax") { - srcParts = src.split(/\s+/, 2); - - if (srcParts.length > 1) { - obj.src = srcParts.shift(); - - obj.opts.filter = srcParts.shift(); - } - } - - // Hide all buttons and disable interactivity for modal items - if (obj.opts.modal) { - obj.opts = $.extend(true, obj.opts, { - trapFocus: true, - // Remove buttons - infobar: 0, - toolbar: 0, - - smallBtn: 0, - - // Disable keyboard navigation - keyboard: 0, - - // Disable some modules - slideShow: 0, - fullScreen: 0, - thumbs: 0, - touch: 0, - - // Disable click event handlers - clickContent: false, - clickSlide: false, - clickOutside: false, - dblclickContent: false, - dblclickSlide: false, - dblclickOutside: false - }); - } - - // Step 4 - Add processed object to group - // ====================================== - - self.group.push(obj); - }); - - // Update controls if gallery is already opened - if (Object.keys(self.slides).length) { - self.updateControls(); - - // Update thumbnails, if needed - thumbs = self.Thumbs; - - if (thumbs && thumbs.isActive) { - thumbs.create(); - - thumbs.focus(); - } - } - }, - - // Attach an event handler functions for: - // - navigation buttons - // - browser scrolling, resizing; - // - focusing - // - keyboard - // - detecting inactivity - // ====================================== - - addEvents: function () { - var self = this; - - self.removeEvents(); - - // Make navigation elements clickable - // ================================== - - self.$refs.container - .on("click.fb-close", "[data-fancybox-close]", function (e) { - e.stopPropagation(); - e.preventDefault(); - - self.close(e); - }) - .on("touchstart.fb-prev click.fb-prev", "[data-fancybox-prev]", function (e) { - e.stopPropagation(); - e.preventDefault(); - - self.previous(); - }) - .on("touchstart.fb-next click.fb-next", "[data-fancybox-next]", function (e) { - e.stopPropagation(); - e.preventDefault(); - - self.next(); - }) - .on("click.fb", "[data-fancybox-zoom]", function (e) { - // Click handler for zoom button - self[self.isScaledDown() ? "scaleToActual" : "scaleToFit"](); - }); - - // Handle page scrolling and browser resizing - // ========================================== - - $W.on("orientationchange.fb resize.fb", function (e) { - if (e && e.originalEvent && e.originalEvent.type === "resize") { - if (self.requestId) { - cancelAFrame(self.requestId); - } - - self.requestId = requestAFrame(function () { - self.update(e); - }); - } else { - if (self.current && self.current.type === "iframe") { - self.$refs.stage.hide(); - } - - setTimeout( - function () { - self.$refs.stage.show(); - - self.update(e); - }, - $.fancybox.isMobile ? 600 : 250 - ); - } - }); - - $D.on("keydown.fb", function (e) { - var instance = $.fancybox ? $.fancybox.getInstance() : null, - current = instance.current, - keycode = e.keyCode || e.which; - - // Trap keyboard focus inside of the modal - // ======================================= - - if (keycode == 9) { - if (current.opts.trapFocus) { - self.focus(e); - } - - return; - } - - // Enable keyboard navigation - // ========================== - - if (!current.opts.keyboard || e.ctrlKey || e.altKey || e.shiftKey || $(e.target).is("input,textarea,video,audio,select")) { - return; - } - - // Backspace and Esc keys - if (keycode === 8 || keycode === 27) { - e.preventDefault(); - - self.close(e); - - return; - } - - // Left arrow and Up arrow - if (keycode === 37 || keycode === 38) { - e.preventDefault(); - - self.previous(); - - return; - } - - // Righ arrow and Down arrow - if (keycode === 39 || keycode === 40) { - e.preventDefault(); - - self.next(); - - return; - } - - self.trigger("afterKeydown", e, keycode); - }); - - // Hide controls after some inactivity period - if (self.group[self.currIndex].opts.idleTime) { - self.idleSecondsCounter = 0; - - $D.on( - "mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle", - function (e) { - self.idleSecondsCounter = 0; - - if (self.isIdle) { - self.showControls(); - } - - self.isIdle = false; - } - ); - - self.idleInterval = window.setInterval(function () { - self.idleSecondsCounter++; - - if (self.idleSecondsCounter >= self.group[self.currIndex].opts.idleTime && !self.isDragging) { - self.isIdle = true; - self.idleSecondsCounter = 0; - - self.hideControls(); - } - }, 1000); - } - }, - - // Remove events added by the core - // =============================== - - removeEvents: function () { - var self = this; - - $W.off("orientationchange.fb resize.fb"); - $D.off("keydown.fb .fb-idle"); - - this.$refs.container.off(".fb-close .fb-prev .fb-next"); - - if (self.idleInterval) { - window.clearInterval(self.idleInterval); - - self.idleInterval = null; - } - }, - - // Change to previous gallery item - // =============================== - - previous: function (duration) { - return this.jumpTo(this.currPos - 1, duration); - }, - - // Change to next gallery item - // =========================== - - next: function (duration) { - return this.jumpTo(this.currPos + 1, duration); - }, - - // Switch to selected gallery item - // =============================== - - jumpTo: function (pos, duration) { - var self = this, - groupLen = self.group.length, - firstRun, - isMoved, - loop, - current, - previous, - slidePos, - stagePos, - prop, - diff; - - if (self.isDragging || self.isClosing || (self.isAnimating && self.firstRun)) { - return; - } - - // Should loop? - pos = parseInt(pos, 10); - loop = self.current ? self.current.opts.loop : self.opts.loop; - - if (!loop && (pos < 0 || pos >= groupLen)) { - return false; - } - - // Check if opening for the first time; this helps to speed things up - firstRun = self.firstRun = !Object.keys(self.slides).length; - - // Create slides - previous = self.current; - - self.prevIndex = self.currIndex; - self.prevPos = self.currPos; - - current = self.createSlide(pos); - - if (groupLen > 1) { - if (loop || current.index < groupLen - 1) { - self.createSlide(pos + 1); - } - - if (loop || current.index > 0) { - self.createSlide(pos - 1); - } - } - - self.current = current; - self.currIndex = current.index; - self.currPos = current.pos; - - self.trigger("beforeShow", firstRun); - - self.updateControls(); - - // Validate duration length - current.forcedDuration = undefined; - - if ($.isNumeric(duration)) { - current.forcedDuration = duration; - } else { - duration = current.opts[firstRun ? "animationDuration" : "transitionDuration"]; - } - - duration = parseInt(duration, 10); - - // Check if user has swiped the slides or if still animating - isMoved = self.isMoved(current); - - // Make sure current slide is visible - current.$slide.addClass("fancybox-slide--current"); - - // Fresh start - reveal container, current slide and start loading content - if (firstRun) { - if (current.opts.animationEffect && duration) { - self.$refs.container.css("transition-duration", duration + "ms"); - } - - self.$refs.container.addClass("fancybox-is-open").trigger("focus"); - - // Attempt to load content into slide - // This will later call `afterLoad` -> `revealContent` - self.loadSlide(current); - - self.preload("image"); - - return; - } - - // Get actual slide/stage positions (before cleaning up) - slidePos = $.fancybox.getTranslate(previous.$slide); - stagePos = $.fancybox.getTranslate(self.$refs.stage); - - // Clean up all slides - $.each(self.slides, function (index, slide) { - $.fancybox.stop(slide.$slide, true); - }); - - if (previous.pos !== current.pos) { - previous.isComplete = false; - } - - previous.$slide.removeClass("fancybox-slide--complete fancybox-slide--current"); - - // If slides are out of place, then animate them to correct position - if (isMoved) { - // Calculate horizontal swipe distance - diff = slidePos.left - (previous.pos * slidePos.width + previous.pos * previous.opts.gutter); - - $.each(self.slides, function (index, slide) { - slide.$slide.removeClass("fancybox-animated").removeClass(function (index, className) { - return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" "); - }); - - // Make sure that each slide is in equal distance - // This is mostly needed for freshly added slides, because they are not yet positioned - var leftPos = slide.pos * slidePos.width + slide.pos * slide.opts.gutter; - - $.fancybox.setTranslate(slide.$slide, { - top: 0, - left: leftPos - stagePos.left + diff - }); - - if (slide.pos !== current.pos) { - slide.$slide.addClass("fancybox-slide--" + (slide.pos > current.pos ? "next" : "previous")); - } - - // Redraw to make sure that transition will start - forceRedraw(slide.$slide); - - // Animate the slide - $.fancybox.animate( - slide.$slide, { - top: 0, - left: (slide.pos - current.pos) * slidePos.width + (slide.pos - current.pos) * slide.opts.gutter - }, - duration, - function () { - slide.$slide - .css({ - transform: "", - opacity: "" - }) - .removeClass("fancybox-slide--next fancybox-slide--previous"); - - if (slide.pos === self.currPos) { - self.complete(); - } - } - ); - }); - } else if (duration && current.opts.transitionEffect) { - // Set transition effect for previously active slide - prop = "fancybox-animated fancybox-fx-" + current.opts.transitionEffect; - - previous.$slide.addClass("fancybox-slide--" + (previous.pos > current.pos ? "next" : "previous")); - - $.fancybox.animate( - previous.$slide, - prop, - duration, - function () { - previous.$slide.removeClass(prop).removeClass("fancybox-slide--next fancybox-slide--previous"); - }, - false - ); - } - - if (current.isLoaded) { - self.revealContent(current); - } else { - self.loadSlide(current); - } - - self.preload("image"); - }, - - // Create new "slide" element - // These are gallery items that are actually added to DOM - // ======================================================= - - createSlide: function (pos) { - var self = this, - $slide, - index; - - index = pos % self.group.length; - index = index < 0 ? self.group.length + index : index; - - if (!self.slides[pos] && self.group[index]) { - $slide = $('
').appendTo(self.$refs.stage); - - self.slides[pos] = $.extend(true, {}, self.group[index], { - pos: pos, - $slide: $slide, - isLoaded: false - }); - - self.updateSlide(self.slides[pos]); - } - - return self.slides[pos]; - }, - - // Scale image to the actual size of the image; - // x and y values should be relative to the slide - // ============================================== - - scaleToActual: function (x, y, duration) { - var self = this, - current = self.current, - $content = current.$content, - canvasWidth = $.fancybox.getTranslate(current.$slide).width, - canvasHeight = $.fancybox.getTranslate(current.$slide).height, - newImgWidth = current.width, - newImgHeight = current.height, - imgPos, - posX, - posY, - scaleX, - scaleY; - - if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) { - return; - } - - self.isAnimating = true; - - $.fancybox.stop($content); - - x = x === undefined ? canvasWidth * 0.5 : x; - y = y === undefined ? canvasHeight * 0.5 : y; - - imgPos = $.fancybox.getTranslate($content); - - imgPos.top -= $.fancybox.getTranslate(current.$slide).top; - imgPos.left -= $.fancybox.getTranslate(current.$slide).left; - - scaleX = newImgWidth / imgPos.width; - scaleY = newImgHeight / imgPos.height; - - // Get center position for original image - posX = canvasWidth * 0.5 - newImgWidth * 0.5; - posY = canvasHeight * 0.5 - newImgHeight * 0.5; - - // Make sure image does not move away from edges - if (newImgWidth > canvasWidth) { - posX = imgPos.left * scaleX - (x * scaleX - x); - - if (posX > 0) { - posX = 0; - } - - if (posX < canvasWidth - newImgWidth) { - posX = canvasWidth - newImgWidth; - } - } - - if (newImgHeight > canvasHeight) { - posY = imgPos.top * scaleY - (y * scaleY - y); - - if (posY > 0) { - posY = 0; - } - - if (posY < canvasHeight - newImgHeight) { - posY = canvasHeight - newImgHeight; - } - } - - self.updateCursor(newImgWidth, newImgHeight); - - $.fancybox.animate( - $content, { - top: posY, - left: posX, - scaleX: scaleX, - scaleY: scaleY - }, - duration || 366, - function () { - self.isAnimating = false; - } - ); - - // Stop slideshow - if (self.SlideShow && self.SlideShow.isActive) { - self.SlideShow.stop(); - } - }, - - // Scale image to fit inside parent element - // ======================================== - - scaleToFit: function (duration) { - var self = this, - current = self.current, - $content = current.$content, - end; - - if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) { - return; - } - - self.isAnimating = true; - - $.fancybox.stop($content); - - end = self.getFitPos(current); - - self.updateCursor(end.width, end.height); - - $.fancybox.animate( - $content, { - top: end.top, - left: end.left, - scaleX: end.width / $content.width(), - scaleY: end.height / $content.height() - }, - duration || 366, - function () { - self.isAnimating = false; - } - ); - }, - - // Calculate image size to fit inside viewport - // =========================================== - - getFitPos: function (slide) { - var self = this, - $content = slide.$content, - $slide = slide.$slide, - width = slide.width || slide.opts.width, - height = slide.height || slide.opts.height, - maxWidth, - maxHeight, - minRatio, - aspectRatio, - rez = {}; - - if (!slide.isLoaded || !$content || !$content.length) { - return false; - } - - maxWidth = $.fancybox.getTranslate(self.$refs.stage).width; - maxHeight = $.fancybox.getTranslate(self.$refs.stage).height; - - maxWidth -= - parseFloat($slide.css("paddingLeft")) + - parseFloat($slide.css("paddingRight")) + - parseFloat($content.css("marginLeft")) + - parseFloat($content.css("marginRight")); - - maxHeight -= - parseFloat($slide.css("paddingTop")) + - parseFloat($slide.css("paddingBottom")) + - parseFloat($content.css("marginTop")) + - parseFloat($content.css("marginBottom")); - - if (!width || !height) { - width = maxWidth; - height = maxHeight; - } - - minRatio = Math.min(1, maxWidth / width, maxHeight / height); - - width = minRatio * width; - height = minRatio * height; - - // Adjust width/height to precisely fit into container - if (width > maxWidth - 0.5) { - width = maxWidth; - } - - if (height > maxHeight - 0.5) { - height = maxHeight; - } - - if (slide.type === "image") { - rez.top = Math.floor((maxHeight - height) * 0.5) + parseFloat($slide.css("paddingTop")); - rez.left = Math.floor((maxWidth - width) * 0.5) + parseFloat($slide.css("paddingLeft")); - } else if (slide.contentType === "video") { - // Force aspect ratio for the video - // "I say the whole world must learn of our peaceful ways… by force!" - aspectRatio = slide.opts.width && slide.opts.height ? width / height : slide.opts.ratio || 16 / 9; - - if (height > width / aspectRatio) { - height = width / aspectRatio; - } else if (width > height * aspectRatio) { - width = height * aspectRatio; - } - } - - rez.width = width; - rez.height = height; - - return rez; - }, - - // Update content size and position for all slides - // ============================================== - - update: function (e) { - var self = this; - - $.each(self.slides, function (key, slide) { - self.updateSlide(slide, e); - }); - }, - - // Update slide content position and size - // ====================================== - - updateSlide: function (slide, e) { - var self = this, - $content = slide && slide.$content, - width = slide.width || slide.opts.width, - height = slide.height || slide.opts.height, - $slide = slide.$slide; - - // First, prevent caption overlap, if needed - self.adjustCaption(slide); - - // Then resize content to fit inside the slide - if ($content && (width || height || slide.contentType === "video") && !slide.hasError) { - $.fancybox.stop($content); - - $.fancybox.setTranslate($content, self.getFitPos(slide)); - - if (slide.pos === self.currPos) { - self.isAnimating = false; - - self.updateCursor(); - } - } - - // Then some adjustments - self.adjustLayout(slide); - - if ($slide.length) { - $slide.trigger("refresh"); - - if (slide.pos === self.currPos) { - self.$refs.toolbar - .add(self.$refs.navigation.find(".fancybox-button--arrow_right")) - .toggleClass("compensate-for-scrollbar", $slide.get(0).scrollHeight > $slide.get(0).clientHeight); - } - } - - self.trigger("onUpdate", slide, e); - }, - - // Horizontally center slide - // ========================= - - centerSlide: function (duration) { - var self = this, - current = self.current, - $slide = current.$slide; - - if (self.isClosing || !current) { - return; - } - - $slide.siblings().css({ - transform: "", - opacity: "" - }); - - $slide - .parent() - .children() - .removeClass("fancybox-slide--previous fancybox-slide--next"); - - $.fancybox.animate( - $slide, { - top: 0, - left: 0, - opacity: 1 - }, - duration === undefined ? 0 : duration, - function () { - // Clean up - $slide.css({ - transform: "", - opacity: "" - }); - - if (!current.isComplete) { - self.complete(); - } - }, - false - ); - }, - - // Check if current slide is moved (swiped) - // ======================================== - - isMoved: function (slide) { - var current = slide || this.current, - slidePos, - stagePos; - - if (!current) { - return false; - } - - stagePos = $.fancybox.getTranslate(this.$refs.stage); - slidePos = $.fancybox.getTranslate(current.$slide); - - return ( - !current.$slide.hasClass("fancybox-animated") && - (Math.abs(slidePos.top - stagePos.top) > 0.5 || Math.abs(slidePos.left - stagePos.left) > 0.5) - ); - }, - - // Update cursor style depending if content can be zoomed - // ====================================================== - - updateCursor: function (nextWidth, nextHeight) { - var self = this, - current = self.current, - $container = self.$refs.container, - canPan, - isZoomable; - - if (!current || self.isClosing || !self.Guestures) { - return; - } - - $container.removeClass("fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-zoomOut fancybox-can-swipe fancybox-can-pan"); - - canPan = self.canPan(nextWidth, nextHeight); - - isZoomable = canPan ? true : self.isZoomable(); - - $container.toggleClass("fancybox-is-zoomable", isZoomable); - - $("[data-fancybox-zoom]").prop("disabled", !isZoomable); - - if (canPan) { - $container.addClass("fancybox-can-pan"); - } else if ( - isZoomable && - (current.opts.clickContent === "zoom" || ($.isFunction(current.opts.clickContent) && current.opts.clickContent(current) == "zoom")) - ) { - $container.addClass("fancybox-can-zoomIn"); - } else if (current.opts.touch && (current.opts.touch.vertical || self.group.length > 1) && current.contentType !== "video") { - $container.addClass("fancybox-can-swipe"); - } - }, - - // Check if current slide is zoomable - // ================================== - - isZoomable: function () { - var self = this, - current = self.current, - fitPos; - - // Assume that slide is zoomable if: - // - image is still loading - // - actual size of the image is smaller than available area - if (current && !self.isClosing && current.type === "image" && !current.hasError) { - if (!current.isLoaded) { - return true; - } - - fitPos = self.getFitPos(current); - - if (fitPos && (current.width > fitPos.width || current.height > fitPos.height)) { - return true; - } - } - - return false; - }, - - // Check if current image dimensions are smaller than actual - // ========================================================= - - isScaledDown: function (nextWidth, nextHeight) { - var self = this, - rez = false, - current = self.current, - $content = current.$content; - - if (nextWidth !== undefined && nextHeight !== undefined) { - rez = nextWidth < current.width && nextHeight < current.height; - } else if ($content) { - rez = $.fancybox.getTranslate($content); - rez = rez.width < current.width && rez.height < current.height; - } - - return rez; - }, - - // Check if image dimensions exceed parent element - // =============================================== - - canPan: function (nextWidth, nextHeight) { - var self = this, - current = self.current, - pos = null, - rez = false; - - if (current.type === "image" && (current.isComplete || (nextWidth && nextHeight)) && !current.hasError) { - rez = self.getFitPos(current); - - if (nextWidth !== undefined && nextHeight !== undefined) { - pos = { - width: nextWidth, - height: nextHeight - }; - } else if (current.isComplete) { - pos = $.fancybox.getTranslate(current.$content); - } - - if (pos && rez) { - rez = Math.abs(pos.width - rez.width) > 1.5 || Math.abs(pos.height - rez.height) > 1.5; - } - } - - return rez; - }, - - // Load content into the slide - // =========================== - - loadSlide: function (slide) { - var self = this, - type, - $slide, - ajaxLoad; - - if (slide.isLoading || slide.isLoaded) { - return; - } - - slide.isLoading = true; - - if (self.trigger("beforeLoad", slide) === false) { - slide.isLoading = false; - - return false; - } - - type = slide.type; - $slide = slide.$slide; - - $slide - .off("refresh") - .trigger("onReset") - .addClass(slide.opts.slideClass); - - // Create content depending on the type - switch (type) { - case "image": - self.setImage(slide); - - break; - - case "iframe": - self.setIframe(slide); - - break; - - case "html": - self.setContent(slide, slide.src || slide.content); - - break; - - case "video": - self.setContent( - slide, - slide.opts.video.tpl - .replace(/\{\{src\}\}/gi, slide.src) - .replace("{{format}}", slide.opts.videoFormat || slide.opts.video.format || "") - .replace("{{poster}}", slide.thumb || "") - ); - - break; - - case "inline": - if ($(slide.src).length) { - self.setContent(slide, $(slide.src)); - } else { - self.setError(slide); - } - - break; - - case "ajax": - self.showLoading(slide); - - ajaxLoad = $.ajax( - $.extend({}, slide.opts.ajax.settings, { - url: slide.src, - success: function (data, textStatus) { - if (textStatus === "success") { - self.setContent(slide, data); - } - }, - error: function (jqXHR, textStatus) { - if (jqXHR && textStatus !== "abort") { - self.setError(slide); - } - } - }) - ); - - $slide.one("onReset", function () { - ajaxLoad.abort(); - }); - - break; - - default: - self.setError(slide); - - break; - } - - return true; - }, - - // Use thumbnail image, if possible - // ================================ - - setImage: function (slide) { - var self = this, - ghost; - - // Check if need to show loading icon - setTimeout(function () { - var $img = slide.$image; - - if (!self.isClosing && slide.isLoading && (!$img || !$img.length || !$img[0].complete) && !slide.hasError) { - self.showLoading(slide); - } - }, 50); - - //Check if image has srcset - self.checkSrcset(slide); - - // This will be wrapper containing both ghost and actual image - slide.$content = $('
') - .addClass("fancybox-is-hidden") - .appendTo(slide.$slide.addClass("fancybox-slide--image")); - - // If we have a thumbnail, we can display it while actual image is loading - // Users will not stare at black screen and actual image will appear gradually - if (slide.opts.preload !== false && slide.opts.width && slide.opts.height && slide.thumb) { - slide.width = slide.opts.width; - slide.height = slide.opts.height; - - ghost = document.createElement("img"); - - ghost.onerror = function () { - $(this).remove(); - - slide.$ghost = null; - }; - - ghost.onload = function () { - self.afterLoad(slide); - }; - - slide.$ghost = $(ghost) - .addClass("fancybox-image") - .appendTo(slide.$content) - .attr("src", slide.thumb); - } - - // Start loading actual image - self.setBigImage(slide); - }, - - // Check if image has srcset and get the source - // ============================================ - checkSrcset: function (slide) { - var srcset = slide.opts.srcset || slide.opts.image.srcset, - found, - temp, - pxRatio, - windowWidth; - - // If we have "srcset", then we need to find first matching "src" value. - // This is necessary, because when you set an src attribute, the browser will preload the image - // before any javascript or even CSS is applied. - if (srcset) { - pxRatio = window.devicePixelRatio || 1; - windowWidth = window.innerWidth * pxRatio; - - temp = srcset.split(",").map(function (el) { - var ret = {}; - - el.trim() - .split(/\s+/) - .forEach(function (el, i) { - var value = parseInt(el.substring(0, el.length - 1), 10); - - if (i === 0) { - return (ret.url = el); - } - - if (value) { - ret.value = value; - ret.postfix = el[el.length - 1]; - } - }); - - return ret; - }); - - // Sort by value - temp.sort(function (a, b) { - return a.value - b.value; - }); - - // Ok, now we have an array of all srcset values - for (var j = 0; j < temp.length; j++) { - var el = temp[j]; - - if ((el.postfix === "w" && el.value >= windowWidth) || (el.postfix === "x" && el.value >= pxRatio)) { - found = el; - break; - } - } - - // If not found, take the last one - if (!found && temp.length) { - found = temp[temp.length - 1]; - } - - if (found) { - slide.src = found.url; - - // If we have default width/height values, we can calculate height for matching source - if (slide.width && slide.height && found.postfix == "w") { - slide.height = (slide.width / slide.height) * found.value; - slide.width = found.value; - } - - slide.opts.srcset = srcset; - } - } - }, - - // Create full-size image - // ====================== - - setBigImage: function (slide) { - var self = this, - img = document.createElement("img"), - $img = $(img); - - slide.$image = $img - .one("error", function () { - self.setError(slide); - }) - .one("load", function () { - var sizes; - - if (!slide.$ghost) { - self.resolveImageSlideSize(slide, this.naturalWidth, this.naturalHeight); - - self.afterLoad(slide); - } - - if (self.isClosing) { - return; - } - - if (slide.opts.srcset) { - sizes = slide.opts.sizes; - - if (!sizes || sizes === "auto") { - sizes = - (slide.width / slide.height > 1 && $W.width() / $W.height() > 1 ? "100" : Math.round((slide.width / slide.height) * 100)) + - "vw"; - } - - $img.attr("sizes", sizes).attr("srcset", slide.opts.srcset); - } - - // Hide temporary image after some delay - if (slide.$ghost) { - setTimeout(function () { - if (slide.$ghost && !self.isClosing) { - slide.$ghost.hide(); - } - }, Math.min(300, Math.max(1000, slide.height / 1600))); - } - - self.hideLoading(slide); - }) - .addClass("fancybox-image") - .attr("src", slide.src) - .appendTo(slide.$content); - - if ((img.complete || img.readyState == "complete") && $img.naturalWidth && $img.naturalHeight) { - $img.trigger("load"); - } else if (img.error) { - $img.trigger("error"); - } - }, - - // Computes the slide size from image size and maxWidth/maxHeight - // ============================================================== - - resolveImageSlideSize: function (slide, imgWidth, imgHeight) { - var maxWidth = parseInt(slide.opts.width, 10), - maxHeight = parseInt(slide.opts.height, 10); - - // Sets the default values from the image - slide.width = imgWidth; - slide.height = imgHeight; - - if (maxWidth > 0) { - slide.width = maxWidth; - slide.height = Math.floor((maxWidth * imgHeight) / imgWidth); - } - - if (maxHeight > 0) { - slide.width = Math.floor((maxHeight * imgWidth) / imgHeight); - slide.height = maxHeight; - } - }, - - // Create iframe wrapper, iframe and bindings - // ========================================== - - setIframe: function (slide) { - var self = this, - opts = slide.opts.iframe, - $slide = slide.$slide, - $iframe; - - slide.$content = $('
') - .css(opts.css) - .appendTo($slide); - - $slide.addClass("fancybox-slide--" + slide.contentType); - - slide.$iframe = $iframe = $(opts.tpl.replace(/\{rnd\}/g, new Date().getTime())) - .attr(opts.attr) - .appendTo(slide.$content); - - if (opts.preload) { - self.showLoading(slide); - - // Unfortunately, it is not always possible to determine if iframe is successfully loaded - // (due to browser security policy) - - $iframe.on("load.fb error.fb", function (e) { - this.isReady = 1; - - slide.$slide.trigger("refresh"); - - self.afterLoad(slide); - }); - - // Recalculate iframe content size - // =============================== - - $slide.on("refresh.fb", function () { - var $content = slide.$content, - frameWidth = opts.css.width, - frameHeight = opts.css.height, - $contents, - $body; - - if ($iframe[0].isReady !== 1) { - return; - } - - try { - $contents = $iframe.contents(); - $body = $contents.find("body"); - } catch (ignore) {} - - // Calculate content dimensions, if it is accessible - if ($body && $body.length && $body.children().length) { - // Avoid scrolling to top (if multiple instances) - $slide.css("overflow", "visible"); - - $content.css({ - width: "100%", - "max-width": "100%", - height: "9999px" - }); - - if (frameWidth === undefined) { - frameWidth = Math.ceil(Math.max($body[0].clientWidth, $body.outerWidth(true))); - } - - $content.css("width", frameWidth ? frameWidth : "").css("max-width", ""); - - if (frameHeight === undefined) { - frameHeight = Math.ceil(Math.max($body[0].clientHeight, $body.outerHeight(true))); - } - - $content.css("height", frameHeight ? frameHeight : ""); - - $slide.css("overflow", "auto"); - } - - $content.removeClass("fancybox-is-hidden"); - }); - } else { - self.afterLoad(slide); - } - - $iframe.attr("src", slide.src); - - // Remove iframe if closing or changing gallery item - $slide.one("onReset", function () { - // This helps IE not to throw errors when closing - try { - $(this) - .find("iframe") - .hide() - .unbind() - .attr("src", "//about:blank"); - } catch (ignore) {} - - $(this) - .off("refresh.fb") - .empty(); - - slide.isLoaded = false; - slide.isRevealed = false; - }); - }, - - // Wrap and append content to the slide - // ====================================== - - setContent: function (slide, content) { - var self = this; - - if (self.isClosing) { - return; - } - - self.hideLoading(slide); - - if (slide.$content) { - $.fancybox.stop(slide.$content); - } - - slide.$slide.empty(); - - // If content is a jQuery object, then it will be moved to the slide. - // The placeholder is created so we will know where to put it back. - if (isQuery(content) && content.parent().length) { - // Make sure content is not already moved to fancyBox - if (content.hasClass("fancybox-content") || content.parent().hasClass("fancybox-content")) { - content.parents(".fancybox-slide").trigger("onReset"); - } - - // Create temporary element marking original place of the content - slide.$placeholder = $("
") - .hide() - .insertAfter(content); - - // Make sure content is visible - content.css("display", "inline-block"); - } else if (!slide.hasError) { - // If content is just a plain text, try to convert it to html - if ($.type(content) === "string") { - content = $("
") - .append($.trim(content)) - .contents(); - } - - // If "filter" option is provided, then filter content - if (slide.opts.filter) { - content = $("
") - .html(content) - .find(slide.opts.filter); - } - } - - slide.$slide.one("onReset", function () { - // Pause all html5 video/audio - $(this) - .find("video,audio") - .trigger("pause"); - - // Put content back - if (slide.$placeholder) { - slide.$placeholder.after(content.removeClass("fancybox-content").hide()).remove(); - - slide.$placeholder = null; - } - - // Remove custom close button - if (slide.$smallBtn) { - slide.$smallBtn.remove(); - - slide.$smallBtn = null; - } - - // Remove content and mark slide as not loaded - if (!slide.hasError) { - $(this).empty(); - - slide.isLoaded = false; - slide.isRevealed = false; - } - }); - - $(content).appendTo(slide.$slide); - - if ($(content).is("video,audio")) { - $(content).addClass("fancybox-video"); - - $(content).wrap("
"); - - slide.contentType = "video"; - - slide.opts.width = slide.opts.width || $(content).attr("width"); - slide.opts.height = slide.opts.height || $(content).attr("height"); - } - - slide.$content = slide.$slide - .children() - .filter("div,form,main,video,audio,article,.fancybox-content") - .first(); - - slide.$content.siblings().hide(); - - // Re-check if there is a valid content - // (in some cases, ajax response can contain various elements or plain text) - if (!slide.$content.length) { - slide.$content = slide.$slide - .wrapInner("
") - .children() - .first(); - } - - slide.$content.addClass("fancybox-content"); - - slide.$slide.addClass("fancybox-slide--" + slide.contentType); - - self.afterLoad(slide); - }, - - // Display error message - // ===================== - - setError: function (slide) { - slide.hasError = true; - - slide.$slide - .trigger("onReset") - .removeClass("fancybox-slide--" + slide.contentType) - .addClass("fancybox-slide--error"); - - slide.contentType = "html"; - - this.setContent(slide, this.translate(slide, slide.opts.errorTpl)); - - if (slide.pos === this.currPos) { - this.isAnimating = false; - } - }, - - // Show loading icon inside the slide - // ================================== - - showLoading: function (slide) { - var self = this; - - slide = slide || self.current; - - if (slide && !slide.$spinner) { - slide.$spinner = $(self.translate(self, self.opts.spinnerTpl)) - .appendTo(slide.$slide) - .hide() - .fadeIn("fast"); - } - }, - - // Remove loading icon from the slide - // ================================== - - hideLoading: function (slide) { - var self = this; - - slide = slide || self.current; - - if (slide && slide.$spinner) { - slide.$spinner.stop().remove(); - - delete slide.$spinner; - } - }, - - // Adjustments after slide content has been loaded - // =============================================== - - afterLoad: function (slide) { - var self = this; - - if (self.isClosing) { - return; - } - - slide.isLoading = false; - slide.isLoaded = true; - - self.trigger("afterLoad", slide); - - self.hideLoading(slide); - - // Add small close button - if (slide.opts.smallBtn && (!slide.$smallBtn || !slide.$smallBtn.length)) { - slide.$smallBtn = $(self.translate(slide, slide.opts.btnTpl.smallBtn)).appendTo(slide.$content); - } - - // Disable right click - if (slide.opts.protect && slide.$content && !slide.hasError) { - slide.$content.on("contextmenu.fb", function (e) { - if (e.button == 2) { - e.preventDefault(); - } - - return true; - }); - - // Add fake element on top of the image - // This makes a bit harder for user to select image - if (slide.type === "image") { - $('
').appendTo(slide.$content); - } - } - - self.adjustCaption(slide); - - self.adjustLayout(slide); - - if (slide.pos === self.currPos) { - self.updateCursor(); - } - - self.revealContent(slide); - }, - - // Prevent caption overlap, - // fix css inconsistency across browsers - // ===================================== - - adjustCaption: function (slide) { - var self = this, - current = slide || self.current, - caption = current.opts.caption, - preventOverlap = current.opts.preventCaptionOverlap, - $caption = self.$refs.caption, - $clone, - captionH = false; - - $caption.toggleClass("fancybox-caption--separate", preventOverlap); - - if (preventOverlap && caption && caption.length) { - if (current.pos !== self.currPos) { - $clone = $caption.clone().appendTo($caption.parent()); - - $clone - .children() - .eq(0) - .empty() - .html(caption); - - captionH = $clone.outerHeight(true); - - $clone.empty().remove(); - } else if (self.$caption) { - captionH = self.$caption.outerHeight(true); - } - - current.$slide.css("padding-bottom", captionH || ""); - } - }, - - // Simple hack to fix inconsistency across browsers, described here (affects Edge, too): - // https://bugzilla.mozilla.org/show_bug.cgi?id=748518 - // ==================================================================================== - - adjustLayout: function (slide) { - var self = this, - current = slide || self.current, - scrollHeight, - marginBottom, - inlinePadding, - actualPadding; - - if (current.isLoaded && current.opts.disableLayoutFix !== true) { - current.$content.css("margin-bottom", ""); - - // If we would always set margin-bottom for the content, - // then it would potentially break vertical align - if (current.$content.outerHeight() > current.$slide.height() + 0.5) { - inlinePadding = current.$slide[0].style["padding-bottom"]; - actualPadding = current.$slide.css("padding-bottom"); - - if (parseFloat(actualPadding) > 0) { - scrollHeight = current.$slide[0].scrollHeight; - - current.$slide.css("padding-bottom", 0); - - if (Math.abs(scrollHeight - current.$slide[0].scrollHeight) < 1) { - marginBottom = actualPadding; - } - - current.$slide.css("padding-bottom", inlinePadding); - } - } - - current.$content.css("margin-bottom", marginBottom); - } - }, - - // Make content visible - // This method is called right after content has been loaded or - // user navigates gallery and transition should start - // ============================================================ - - revealContent: function (slide) { - var self = this, - $slide = slide.$slide, - end = false, - start = false, - isMoved = self.isMoved(slide), - isRevealed = slide.isRevealed, - effect, - effectClassName, - duration, - opacity; - - slide.isRevealed = true; - - effect = slide.opts[self.firstRun ? "animationEffect" : "transitionEffect"]; - duration = slide.opts[self.firstRun ? "animationDuration" : "transitionDuration"]; - - duration = parseInt(slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10); - - if (isMoved || slide.pos !== self.currPos || !duration) { - effect = false; - } - - // Check if can zoom - if (effect === "zoom") { - if (slide.pos === self.currPos && duration && slide.type === "image" && !slide.hasError && (start = self.getThumbPos(slide))) { - end = self.getFitPos(slide); - } else { - effect = "fade"; - } - } - - // Zoom animation - // ============== - if (effect === "zoom") { - self.isAnimating = true; - - end.scaleX = end.width / start.width; - end.scaleY = end.height / start.height; - - // Check if we need to animate opacity - opacity = slide.opts.zoomOpacity; - - if (opacity == "auto") { - opacity = Math.abs(slide.width / slide.height - start.width / start.height) > 0.1; - } - - if (opacity) { - start.opacity = 0.1; - end.opacity = 1; - } - - // Draw image at start position - $.fancybox.setTranslate(slide.$content.removeClass("fancybox-is-hidden"), start); - - forceRedraw(slide.$content); - - // Start animation - $.fancybox.animate(slide.$content, end, duration, function () { - self.isAnimating = false; - - self.complete(); - }); - - return; - } - - self.updateSlide(slide); - - // Simply show content if no effect - // ================================ - if (!effect) { - slide.$content.removeClass("fancybox-is-hidden"); - - if (!isRevealed && isMoved && slide.type === "image" && !slide.hasError) { - slide.$content.hide().fadeIn("fast"); - } - - if (slide.pos === self.currPos) { - self.complete(); - } - - return; - } - - // Prepare for CSS transiton - // ========================= - $.fancybox.stop($slide); - - //effectClassName = "fancybox-animated fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-fx-" + effect; - effectClassName = "fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-animated fancybox-fx-" + effect; - - $slide.addClass(effectClassName).removeClass("fancybox-slide--current"); //.addClass(effectClassName); - - slide.$content.removeClass("fancybox-is-hidden"); - - // Force reflow - forceRedraw($slide); - - if (slide.type !== "image") { - slide.$content.hide().show(0); - } - - $.fancybox.animate( - $slide, - "fancybox-slide--current", - duration, - function () { - $slide.removeClass(effectClassName).css({ - transform: "", - opacity: "" - }); - - if (slide.pos === self.currPos) { - self.complete(); - } - }, - true - ); - }, - - // Check if we can and have to zoom from thumbnail - //================================================ - - getThumbPos: function (slide) { - var rez = false, - $thumb = slide.$thumb, - thumbPos, - btw, - brw, - bbw, - blw; - - if (!$thumb || !inViewport($thumb[0])) { - return false; - } - - thumbPos = $.fancybox.getTranslate($thumb); - - btw = parseFloat($thumb.css("border-top-width") || 0); - brw = parseFloat($thumb.css("border-right-width") || 0); - bbw = parseFloat($thumb.css("border-bottom-width") || 0); - blw = parseFloat($thumb.css("border-left-width") || 0); - - rez = { - top: thumbPos.top + btw, - left: thumbPos.left + blw, - width: thumbPos.width - brw - blw, - height: thumbPos.height - btw - bbw, - scaleX: 1, - scaleY: 1 - }; - - return thumbPos.width > 0 && thumbPos.height > 0 ? rez : false; - }, - - // Final adjustments after current gallery item is moved to position - // and it`s content is loaded - // ================================================================== - - complete: function () { - var self = this, - current = self.current, - slides = {}, - $el; - - if (self.isMoved() || !current.isLoaded) { - return; - } - - if (!current.isComplete) { - current.isComplete = true; - - current.$slide.siblings().trigger("onReset"); - - self.preload("inline"); - - // Trigger any CSS transiton inside the slide - forceRedraw(current.$slide); - - current.$slide.addClass("fancybox-slide--complete"); - - // Remove unnecessary slides - $.each(self.slides, function (key, slide) { - if (slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1) { - slides[slide.pos] = slide; - } else if (slide) { - $.fancybox.stop(slide.$slide); - - slide.$slide.off().remove(); - } - }); - - self.slides = slides; - } - - self.isAnimating = false; - - self.updateCursor(); - - self.trigger("afterShow"); - - // Autoplay first html5 video/audio - if (!!current.opts.video.autoStart) { - current.$slide - .find("video,audio") - .filter(":visible:first") - .trigger("play") - .one("ended", function () { - if (Document.exitFullscreen) { - Document.exitFullscreen(); - } else if (this.webkitExitFullscreen) { - this.webkitExitFullscreen(); - } - - self.next(); - }); - } - - // Try to focus on the first focusable element - if (current.opts.autoFocus && current.contentType === "html") { - // Look for the first input with autofocus attribute - $el = current.$content.find("input[autofocus]:enabled:visible:first"); - - if ($el.length) { - $el.trigger("focus"); - } else { - self.focus(null, true); - } - } - - // Avoid jumping - current.$slide.scrollTop(0).scrollLeft(0); - }, - - // Preload next and previous slides - // ================================ - - preload: function (type) { - var self = this, - prev, - next; - - if (self.group.length < 2) { - return; - } - - next = self.slides[self.currPos + 1]; - prev = self.slides[self.currPos - 1]; - - if (prev && prev.type === type) { - self.loadSlide(prev); - } - - if (next && next.type === type) { - self.loadSlide(next); - } - }, - - // Try to find and focus on the first focusable element - // ==================================================== - - focus: function (e, firstRun) { - var self = this, - focusableStr = [ - "a[href]", - "area[href]", - 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', - "select:not([disabled]):not([aria-hidden])", - "textarea:not([disabled]):not([aria-hidden])", - "button:not([disabled]):not([aria-hidden])", - "iframe", - "object", - "embed", - "video", - "audio", - "[contenteditable]", - '[tabindex]:not([tabindex^="-"])' - ].join(","), - focusableItems, - focusedItemIndex; - - if (self.isClosing) { - return; - } - - if (e || !self.current || !self.current.isComplete) { - // Focus on any element inside fancybox - focusableItems = self.$refs.container.find("*:visible"); - } else { - // Focus inside current slide - focusableItems = self.current.$slide.find("*:visible" + (firstRun ? ":not(.fancybox-close-small)" : "")); - } - - focusableItems = focusableItems.filter(focusableStr).filter(function () { - return $(this).css("visibility") !== "hidden" && !$(this).hasClass("disabled"); - }); - - if (focusableItems.length) { - focusedItemIndex = focusableItems.index(document.activeElement); - - if (e && e.shiftKey) { - // Back tab - if (focusedItemIndex < 0 || focusedItemIndex == 0) { - e.preventDefault(); - - focusableItems.eq(focusableItems.length - 1).trigger("focus"); - } - } else { - // Outside or Forward tab - if (focusedItemIndex < 0 || focusedItemIndex == focusableItems.length - 1) { - if (e) { - e.preventDefault(); - } - - focusableItems.eq(0).trigger("focus"); - } - } - } else { - self.$refs.container.trigger("focus"); - } - }, - - // Activates current instance - brings container to the front and enables keyboard, - // notifies other instances about deactivating - // ================================================================================= - - activate: function () { - var self = this; - - // Deactivate all instances - $(".fancybox-container").each(function () { - var instance = $(this).data("FancyBox"); - - // Skip self and closing instances - if (instance && instance.id !== self.id && !instance.isClosing) { - instance.trigger("onDeactivate"); - - instance.removeEvents(); - - instance.isVisible = false; - } - }); - - self.isVisible = true; - - if (self.current || self.isIdle) { - self.update(); - - self.updateControls(); - } - - self.trigger("onActivate"); - - self.addEvents(); - }, - - // Start closing procedure - // This will start "zoom-out" animation if needed and clean everything up afterwards - // ================================================================================= - - close: function (e, d) { - var self = this, - current = self.current, - effect, - duration, - $content, - domRect, - opacity, - start, - end; - - var done = function () { - self.cleanUp(e); - }; - - if (self.isClosing) { - return false; - } - - self.isClosing = true; - - // If beforeClose callback prevents closing, make sure content is centered - if (self.trigger("beforeClose", e) === false) { - self.isClosing = false; - - requestAFrame(function () { - self.update(); - }); - - return false; - } - - // Remove all events - // If there are multiple instances, they will be set again by "activate" method - self.removeEvents(); - - $content = current.$content; - effect = current.opts.animationEffect; - duration = $.isNumeric(d) ? d : effect ? current.opts.animationDuration : 0; - - current.$slide.removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated"); - - if (e !== true) { - $.fancybox.stop(current.$slide); - } else { - effect = false; - } - - // Remove other slides - current.$slide - .siblings() - .trigger("onReset") - .remove(); - - // Trigger animations - if (duration) { - self.$refs.container - .removeClass("fancybox-is-open") - .addClass("fancybox-is-closing") - .css("transition-duration", duration + "ms"); - } - - // Clean up - self.hideLoading(current); - - self.hideControls(true); - - self.updateCursor(); - - // Check if possible to zoom-out - if ( - effect === "zoom" && - !($content && duration && current.type === "image" && !self.isMoved() && !current.hasError && (end = self.getThumbPos(current))) - ) { - effect = "fade"; - } - - if (effect === "zoom") { - $.fancybox.stop($content); - - domRect = $.fancybox.getTranslate($content); - - start = { - top: domRect.top, - left: domRect.left, - scaleX: domRect.width / end.width, - scaleY: domRect.height / end.height, - width: end.width, - height: end.height - }; - - // Check if we need to animate opacity - opacity = current.opts.zoomOpacity; - - if (opacity == "auto") { - opacity = Math.abs(current.width / current.height - end.width / end.height) > 0.1; - } - - if (opacity) { - end.opacity = 0; - } - - $.fancybox.setTranslate($content, start); - - forceRedraw($content); - - $.fancybox.animate($content, end, duration, done); - - return true; - } - - if (effect && duration) { - $.fancybox.animate( - current.$slide.addClass("fancybox-slide--previous").removeClass("fancybox-slide--current"), - "fancybox-animated fancybox-fx-" + effect, - duration, - done - ); - } else { - // If skip animation - if (e === true) { - setTimeout(done, duration); - } else { - done(); - } - } - - return true; - }, - - // Final adjustments after removing the instance - // ============================================= - - cleanUp: function (e) { - var self = this, - instance, - $focus = self.current.opts.$orig, - x, - y; - - self.current.$slide.trigger("onReset"); - - self.$refs.container.empty().remove(); - - self.trigger("afterClose", e); - - // Place back focus - if (!!self.current.opts.backFocus) { - if (!$focus || !$focus.length || !$focus.is(":visible")) { - $focus = self.$trigger; - } - - if ($focus && $focus.length) { - x = window.scrollX; - y = window.scrollY; - - $focus.trigger("focus"); - - $("html, body") - .scrollTop(y) - .scrollLeft(x); - } - } - - self.current = null; - - // Check if there are other instances - instance = $.fancybox.getInstance(); - - if (instance) { - instance.activate(); - } else { - $("body").removeClass("fancybox-active compensate-for-scrollbar"); - - $("#fancybox-style-noscroll").remove(); - } - }, - - // Call callback and trigger an event - // ================================== - - trigger: function (name, slide) { - var args = Array.prototype.slice.call(arguments, 1), - self = this, - obj = slide && slide.opts ? slide : self.current, - rez; - - if (obj) { - args.unshift(obj); - } else { - obj = self; - } - - args.unshift(self); - - if ($.isFunction(obj.opts[name])) { - rez = obj.opts[name].apply(obj, args); - } - - if (rez === false) { - return rez; - } - - if (name === "afterClose" || !self.$refs) { - $D.trigger(name + ".fb", args); - } else { - self.$refs.container.trigger(name + ".fb", args); - } - }, - - // Update infobar values, navigation button states and reveal caption - // ================================================================== - - updateControls: function () { - var self = this, - current = self.current, - index = current.index, - $container = self.$refs.container, - $caption = self.$refs.caption, - caption = current.opts.caption; - - // Recalculate content dimensions - current.$slide.trigger("refresh"); - - // Set caption - if (caption && caption.length) { - self.$caption = $caption; - - $caption - .children() - .eq(0) - .html(caption); - } else { - self.$caption = null; - } - - if (!self.hasHiddenControls && !self.isIdle) { - self.showControls(); - } - - // Update info and navigation elements - $container.find("[data-fancybox-count]").html(self.group.length); - $container.find("[data-fancybox-index]").html(index + 1); - - $container.find("[data-fancybox-prev]").prop("disabled", !current.opts.loop && index <= 0); - $container.find("[data-fancybox-next]").prop("disabled", !current.opts.loop && index >= self.group.length - 1); - - if (current.type === "image") { - // Re-enable buttons; update download button source - $container - .find("[data-fancybox-zoom]") - .show() - .end() - .find("[data-fancybox-download]") - .attr("href", current.opts.image.src || current.src) - .show(); - } else if (current.opts.toolbar) { - $container.find("[data-fancybox-download],[data-fancybox-zoom]").hide(); - } - - // Make sure focus is not on disabled button/element - if ($(document.activeElement).is(":hidden,[disabled]")) { - self.$refs.container.trigger("focus"); - } - }, - - // Hide toolbar and caption - // ======================== - - hideControls: function (andCaption) { - var self = this, - arr = ["infobar", "toolbar", "nav"]; - - if (andCaption || !self.current.opts.preventCaptionOverlap) { - arr.push("caption"); - } - - this.$refs.container.removeClass( - arr - .map(function (i) { - return "fancybox-show-" + i; - }) - .join(" ") - ); - - this.hasHiddenControls = true; - }, - - showControls: function () { - var self = this, - opts = self.current ? self.current.opts : self.opts, - $container = self.$refs.container; - - self.hasHiddenControls = false; - self.idleSecondsCounter = 0; - - $container - .toggleClass("fancybox-show-toolbar", !!(opts.toolbar && opts.buttons)) - .toggleClass("fancybox-show-infobar", !!(opts.infobar && self.group.length > 1)) - .toggleClass("fancybox-show-caption", !!self.$caption) - .toggleClass("fancybox-show-nav", !!(opts.arrows && self.group.length > 1)) - .toggleClass("fancybox-is-modal", !!opts.modal); - }, - - // Toggle toolbar and caption - // ========================== - - toggleControls: function () { - if (this.hasHiddenControls) { - this.showControls(); - } else { - this.hideControls(); - } - } - }); - - $.fancybox = { - version: "3.5.7", - defaults: defaults, - - // Get current instance and execute a command. - // - // Examples of usage: - // - // $instance = $.fancybox.getInstance(); - // $.fancybox.getInstance().jumpTo( 1 ); - // $.fancybox.getInstance( 'jumpTo', 1 ); - // $.fancybox.getInstance( function() { - // console.info( this.currIndex ); - // }); - // ====================================================== - - getInstance: function (command) { - var instance = $('.fancybox-container:not(".fancybox-is-closing"):last').data("FancyBox"), - args = Array.prototype.slice.call(arguments, 1); - - if (instance instanceof FancyBox) { - if ($.type(command) === "string") { - instance[command].apply(instance, args); - } else if ($.type(command) === "function") { - command.apply(instance, args); - } - - return instance; - } - - return false; - }, - - // Create new instance - // =================== - - open: function (items, opts, index) { - return new FancyBox(items, opts, index); - }, - - // Close current or all instances - // ============================== - - close: function (all) { - var instance = this.getInstance(); - - if (instance) { - instance.close(); - - // Try to find and close next instance - if (all === true) { - this.close(all); - } - } - }, - - // Close all instances and unbind all events - // ========================================= - - destroy: function () { - this.close(true); - - $D.add("body").off("click.fb-start", "**"); - }, - - // Try to detect mobile devices - // ============================ - - isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent), - - // Detect if 'translate3d' support is available - // ============================================ - - use3d: (function () { - var div = document.createElement("div"); - - return ( - window.getComputedStyle && - window.getComputedStyle(div) && - window.getComputedStyle(div).getPropertyValue("transform") && - !(document.documentMode && document.documentMode < 11) - ); - })(), - - // Helper function to get current visual state of an element - // returns array[ top, left, horizontal-scale, vertical-scale, opacity ] - // ===================================================================== - - getTranslate: function ($el) { - var domRect; - - if (!$el || !$el.length) { - return false; - } - - domRect = $el[0].getBoundingClientRect(); - - return { - top: domRect.top || 0, - left: domRect.left || 0, - width: domRect.width, - height: domRect.height, - opacity: parseFloat($el.css("opacity")) - }; - }, - - // Shortcut for setting "translate3d" properties for element - // Can set be used to set opacity, too - // ======================================================== - - setTranslate: function ($el, props) { - var str = "", - css = {}; - - if (!$el || !props) { - return; - } - - if (props.left !== undefined || props.top !== undefined) { - str = - (props.left === undefined ? $el.position().left : props.left) + - "px, " + - (props.top === undefined ? $el.position().top : props.top) + - "px"; - - if (this.use3d) { - str = "translate3d(" + str + ", 0px)"; - } else { - str = "translate(" + str + ")"; - } - } - - if (props.scaleX !== undefined && props.scaleY !== undefined) { - str += " scale(" + props.scaleX + ", " + props.scaleY + ")"; - } else if (props.scaleX !== undefined) { - str += " scaleX(" + props.scaleX + ")"; - } - - if (str.length) { - css.transform = str; - } - - if (props.opacity !== undefined) { - css.opacity = props.opacity; - } - - if (props.width !== undefined) { - css.width = props.width; - } - - if (props.height !== undefined) { - css.height = props.height; - } - - return $el.css(css); - }, - - // Simple CSS transition handler - // ============================= - - animate: function ($el, to, duration, callback, leaveAnimationName) { - var self = this, - from; - - if ($.isFunction(duration)) { - callback = duration; - duration = null; - } - - self.stop($el); - - from = self.getTranslate($el); - - $el.on(transitionEnd, function (e) { - // Skip events from child elements and z-index change - if (e && e.originalEvent && (!$el.is(e.originalEvent.target) || e.originalEvent.propertyName == "z-index")) { - return; - } - - self.stop($el); - - if ($.isNumeric(duration)) { - $el.css("transition-duration", ""); - } - - if ($.isPlainObject(to)) { - if (to.scaleX !== undefined && to.scaleY !== undefined) { - self.setTranslate($el, { - top: to.top, - left: to.left, - width: from.width * to.scaleX, - height: from.height * to.scaleY, - scaleX: 1, - scaleY: 1 - }); - } - } else if (leaveAnimationName !== true) { - $el.removeClass(to); - } - - if ($.isFunction(callback)) { - callback(e); - } - }); - - if ($.isNumeric(duration)) { - $el.css("transition-duration", duration + "ms"); - } - - // Start animation by changing CSS properties or class name - if ($.isPlainObject(to)) { - if (to.scaleX !== undefined && to.scaleY !== undefined) { - delete to.width; - delete to.height; - - if ($el.parent().hasClass("fancybox-slide--image")) { - $el.parent().addClass("fancybox-is-scaling"); - } - } - - $.fancybox.setTranslate($el, to); - } else { - $el.addClass(to); - } - - // Make sure that `transitionend` callback gets fired - $el.data( - "timer", - setTimeout(function () { - $el.trigger(transitionEnd); - }, duration + 33) - ); - }, - - stop: function ($el, callCallback) { - if ($el && $el.length) { - clearTimeout($el.data("timer")); - - if (callCallback) { - $el.trigger(transitionEnd); - } - - $el.off(transitionEnd).css("transition-duration", ""); - - $el.parent().removeClass("fancybox-is-scaling"); - } - } - }; - - // Default click handler for "fancyboxed" links - // ============================================ - - function _run(e, opts) { - var items = [], - index = 0, - $target, - value, - instance; - - // Avoid opening multiple times - if (e && e.isDefaultPrevented()) { - return; - } - - e.preventDefault(); - - opts = opts || {}; - - if (e && e.data) { - opts = mergeOpts(e.data.options, opts); - } - - $target = opts.$target || $(e.currentTarget).trigger("blur"); - instance = $.fancybox.getInstance(); - - if (instance && instance.$trigger && instance.$trigger.is($target)) { - return; - } - - if (opts.selector) { - items = $(opts.selector); - } else { - // Get all related items and find index for clicked one - value = $target.attr("data-fancybox") || ""; - - if (value) { - items = e.data ? e.data.items : []; - items = items.length ? items.filter('[data-fancybox="' + value + '"]') : $('[data-fancybox="' + value + '"]'); - } else { - items = [$target]; - } - } - - index = $(items).index($target); - - // Sometimes current item can not be found - if (index < 0) { - index = 0; - } - - instance = $.fancybox.open(items, opts, index); - - // Save last active element - instance.$trigger = $target; - } - - // Create a jQuery plugin - // ====================== - - $.fn.fancybox = function (options) { - var selector; - - options = options || {}; - selector = options.selector || false; - - if (selector) { - // Use body element instead of document so it executes first - $("body") - .off("click.fb-start", selector) - .on("click.fb-start", selector, { - options: options - }, _run); - } else { - this.off("click.fb-start").on( - "click.fb-start", { - items: this, - options: options - }, - _run - ); - } - - return this; - }; - - // Self initializing plugin for all elements having `data-fancybox` attribute - // ========================================================================== - - $D.on("click.fb-start", "[data-fancybox]", _run); - - // Enable "trigger elements" - // ========================= - - $D.on("click.fb-start", "[data-fancybox-trigger]", function (e) { - $('[data-fancybox="' + $(this).attr("data-fancybox-trigger") + '"]') - .eq($(this).attr("data-fancybox-index") || 0) - .trigger("click.fb-start", { - $trigger: $(this) - }); - }); - - // Track focus event for better accessibility styling - // ================================================== - (function () { - var buttonStr = ".fancybox-button", - focusStr = "fancybox-focus", - $pressed = null; - - $D.on("mousedown mouseup focus blur", buttonStr, function (e) { - switch (e.type) { - case "mousedown": - $pressed = $(this); - break; - case "mouseup": - $pressed = null; - break; - case "focusin": - $(buttonStr).removeClass(focusStr); - - if (!$(this).is($pressed) && !$(this).is("[disabled]")) { - $(this).addClass(focusStr); - } - break; - case "focusout": - $(buttonStr).removeClass(focusStr); - break; - } - }); - })(); -})(window, document, jQuery); -// ========================================================================== -// -// Media -// Adds additional media type support -// -// ========================================================================== -(function ($) { - "use strict"; - - // Object containing properties for each media type - var defaults = { - youtube: { - matcher: /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i, - params: { - autoplay: 1, - autohide: 1, - fs: 1, - rel: 0, - hd: 1, - wmode: "transparent", - enablejsapi: 1, - html5: 1 - }, - paramPlace: 8, - type: "iframe", - url: "https://www.youtube-nocookie.com/embed/$4", - thumb: "https://img.youtube.com/vi/$4/hqdefault.jpg" - }, - - vimeo: { - matcher: /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/, - params: { - autoplay: 1, - hd: 1, - show_title: 1, - show_byline: 1, - show_portrait: 0, - fullscreen: 1 - }, - paramPlace: 3, - type: "iframe", - url: "//player.vimeo.com/video/$2" - }, - - instagram: { - matcher: /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i, - type: "image", - url: "//$1/p/$2/media/?size=l" - }, - - // Examples: - // http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16 - // https://www.google.com/maps/@37.7852006,-122.4146355,14.65z - // https://www.google.com/maps/@52.2111123,2.9237542,6.61z?hl=en - // https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572 - gmap_place: { - matcher: /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i, - type: "iframe", - url: function (rez) { - return ( - "//maps.google." + - rez[2] + - "/?ll=" + - (rez[9] ? rez[9] + "&z=" + Math.floor(rez[10]) + (rez[12] ? rez[12].replace(/^\//, "&") : "") : rez[12] + "").replace(/\?/, "&") + - "&output=" + - (rez[12] && rez[12].indexOf("layer=c") > 0 ? "svembed" : "embed") - ); - } - }, - - // Examples: - // https://www.google.com/maps/search/Empire+State+Building/ - // https://www.google.com/maps/search/?api=1&query=centurylink+field - // https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393 - gmap_search: { - matcher: /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i, - type: "iframe", - url: function (rez) { - return "//maps.google." + rez[2] + "/maps?q=" + rez[5].replace("query=", "q=").replace("api=1", "") + "&output=embed"; - } - } - }; - - // Formats matching url to final form - var format = function (url, rez, params) { - if (!url) { - return; - } - - params = params || ""; - - if ($.type(params) === "object") { - params = $.param(params, true); - } - - $.each(rez, function (key, value) { - url = url.replace("$" + key, value || ""); - }); - - if (params.length) { - url += (url.indexOf("?") > 0 ? "&" : "?") + params; - } - - return url; - }; - - $(document).on("objectNeedsType.fb", function (e, instance, item) { - var url = item.src || "", - type = false, - media, - thumb, - rez, - params, - urlParams, - paramObj, - provider; - - media = $.extend(true, {}, defaults, item.opts.media); - - // Look for any matching media type - $.each(media, function (providerName, providerOpts) { - rez = url.match(providerOpts.matcher); - - if (!rez) { - return; - } - - type = providerOpts.type; - provider = providerName; - paramObj = {}; - - if (providerOpts.paramPlace && rez[providerOpts.paramPlace]) { - urlParams = rez[providerOpts.paramPlace]; - - if (urlParams[0] == "?") { - urlParams = urlParams.substring(1); - } - - urlParams = urlParams.split("&"); - - for (var m = 0; m < urlParams.length; ++m) { - var p = urlParams[m].split("=", 2); - - if (p.length == 2) { - paramObj[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " ")); - } - } - } - - params = $.extend(true, {}, providerOpts.params, item.opts[providerName], paramObj); - - url = - $.type(providerOpts.url) === "function" ? providerOpts.url.call(this, rez, params, item) : format(providerOpts.url, rez, params); - - thumb = - $.type(providerOpts.thumb) === "function" ? providerOpts.thumb.call(this, rez, params, item) : format(providerOpts.thumb, rez); - - if (providerName === "youtube") { - url = url.replace(/&t=((\d+)m)?(\d+)s/, function (match, p1, m, s) { - return "&start=" + ((m ? parseInt(m, 10) * 60 : 0) + parseInt(s, 10)); - }); - } else if (providerName === "vimeo") { - url = url.replace("&%23", "#"); - } - - return false; - }); - - // If it is found, then change content type and update the url - - if (type) { - if (!item.opts.thumb && !(item.opts.$thumb && item.opts.$thumb.length)) { - item.opts.thumb = thumb; - } - - if (type === "iframe") { - item.opts = $.extend(true, item.opts, { - iframe: { - preload: false, - attr: { - scrolling: "no" - } - } - }); - } - - $.extend(item, { - type: type, - src: url, - origSrc: item.src, - contentSource: provider, - contentType: type === "image" ? "image" : provider == "gmap_place" || provider == "gmap_search" ? "map" : "video" - }); - } else if (url) { - item.type = item.opts.defaultType; - } - }); - - // Load YouTube/Video API on request to detect when video finished playing - var VideoAPILoader = { - youtube: { - src: "https://www.youtube.com/iframe_api", - class: "YT", - loading: false, - loaded: false - }, - - vimeo: { - src: "https://player.vimeo.com/api/player.js", - class: "Vimeo", - loading: false, - loaded: false - }, - - load: function (vendor) { - var _this = this, - script; - - if (this[vendor].loaded) { - setTimeout(function () { - _this.done(vendor); - }); - return; - } - - if (this[vendor].loading) { - return; - } - - this[vendor].loading = true; - - script = document.createElement("script"); - script.type = "text/javascript"; - script.src = this[vendor].src; - - if (vendor === "youtube") { - window.onYouTubeIframeAPIReady = function () { - _this[vendor].loaded = true; - _this.done(vendor); - }; - } else { - script.onload = function () { - _this[vendor].loaded = true; - _this.done(vendor); - }; - } - - document.body.appendChild(script); - }, - done: function (vendor) { - var instance, $el, player; - - if (vendor === "youtube") { - delete window.onYouTubeIframeAPIReady; - } - - instance = $.fancybox.getInstance(); - - if (instance) { - $el = instance.current.$content.find("iframe"); - - if (vendor === "youtube" && YT !== undefined && YT) { - player = new YT.Player($el.attr("id"), { - events: { - onStateChange: function (e) { - if (e.data == 0) { - instance.next(); - } - } - } - }); - } else if (vendor === "vimeo" && Vimeo !== undefined && Vimeo) { - player = new Vimeo.Player($el); - - player.on("ended", function () { - instance.next(); - }); - } - } - } - }; - - $(document).on({ - "afterShow.fb": function (e, instance, current) { - if (instance.group.length > 1 && (current.contentSource === "youtube" || current.contentSource === "vimeo")) { - VideoAPILoader.load(current.contentSource); - } - } - }); -})(jQuery); -// ========================================================================== -// -// Guestures -// Adds touch guestures, handles click and tap events -// -// ========================================================================== -(function (window, document, $) { - "use strict"; - - var requestAFrame = (function () { - return ( - window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - // if all else fails, use setTimeout - function (callback) { - return window.setTimeout(callback, 1000 / 60); - } - ); - })(); - - var cancelAFrame = (function () { - return ( - window.cancelAnimationFrame || - window.webkitCancelAnimationFrame || - window.mozCancelAnimationFrame || - window.oCancelAnimationFrame || - function (id) { - window.clearTimeout(id); - } - ); - })(); - - var getPointerXY = function (e) { - var result = []; - - e = e.originalEvent || e || window.e; - e = e.touches && e.touches.length ? e.touches : e.changedTouches && e.changedTouches.length ? e.changedTouches : [e]; - - for (var key in e) { - if (e[key].pageX) { - result.push({ - x: e[key].pageX, - y: e[key].pageY - }); - } else if (e[key].clientX) { - result.push({ - x: e[key].clientX, - y: e[key].clientY - }); - } - } - - return result; - }; - - var distance = function (point2, point1, what) { - if (!point1 || !point2) { - return 0; - } - - if (what === "x") { - return point2.x - point1.x; - } else if (what === "y") { - return point2.y - point1.y; - } - - return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2)); - }; - - var isClickable = function ($el) { - if ( - $el.is('a,area,button,[role="button"],input,label,select,summary,textarea,video,audio,iframe') || - $.isFunction($el.get(0).onclick) || - $el.data("selectable") - ) { - return true; - } - - // Check for attributes like data-fancybox-next or data-fancybox-close - for (var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++) { - if (atts[i].nodeName.substr(0, 14) === "data-fancybox-") { - return true; - } - } - - return false; - }; - - var hasScrollbars = function (el) { - var overflowY = window.getComputedStyle(el)["overflow-y"], - overflowX = window.getComputedStyle(el)["overflow-x"], - vertical = (overflowY === "scroll" || overflowY === "auto") && el.scrollHeight > el.clientHeight, - horizontal = (overflowX === "scroll" || overflowX === "auto") && el.scrollWidth > el.clientWidth; - - return vertical || horizontal; - }; - - var isScrollable = function ($el) { - var rez = false; - - while (true) { - rez = hasScrollbars($el.get(0)); - - if (rez) { - break; - } - - $el = $el.parent(); - - if (!$el.length || $el.hasClass("fancybox-stage") || $el.is("body")) { - break; - } - } - - return rez; - }; - - var Guestures = function (instance) { - var self = this; - - self.instance = instance; - - self.$bg = instance.$refs.bg; - self.$stage = instance.$refs.stage; - self.$container = instance.$refs.container; - - self.destroy(); - - self.$container.on("touchstart.fb.touch mousedown.fb.touch", $.proxy(self, "ontouchstart")); - }; - - Guestures.prototype.destroy = function () { - var self = this; - - self.$container.off(".fb.touch"); - - $(document).off(".fb.touch"); - - if (self.requestId) { - cancelAFrame(self.requestId); - self.requestId = null; - } - - if (self.tapped) { - clearTimeout(self.tapped); - self.tapped = null; - } - }; - - Guestures.prototype.ontouchstart = function (e) { - var self = this, - $target = $(e.target), - instance = self.instance, - current = instance.current, - $slide = current.$slide, - $content = current.$content, - isTouchDevice = e.type == "touchstart"; - - // Do not respond to both (touch and mouse) events - if (isTouchDevice) { - self.$container.off("mousedown.fb.touch"); - } - - // Ignore right click - if (e.originalEvent && e.originalEvent.button == 2) { - return; - } - - // Ignore taping on links, buttons, input elements - if (!$slide.length || !$target.length || isClickable($target) || isClickable($target.parent())) { - return; - } - // Ignore clicks on the scrollbar - if (!$target.is("img") && e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left) { - return; - } - - // Ignore clicks while zooming or closing - if (!current || instance.isAnimating || current.$slide.hasClass("fancybox-animated")) { - e.stopPropagation(); - e.preventDefault(); - - return; - } - - self.realPoints = self.startPoints = getPointerXY(e); - - if (!self.startPoints.length) { - return; - } - - // Allow other scripts to catch touch event if "touch" is set to false - if (current.touch) { - e.stopPropagation(); - } - - self.startEvent = e; - - self.canTap = true; - self.$target = $target; - self.$content = $content; - self.opts = current.opts.touch; - - self.isPanning = false; - self.isSwiping = false; - self.isZooming = false; - self.isScrolling = false; - self.canPan = instance.canPan(); - - self.startTime = new Date().getTime(); - self.distanceX = self.distanceY = self.distance = 0; - - self.canvasWidth = Math.round($slide[0].clientWidth); - self.canvasHeight = Math.round($slide[0].clientHeight); - - self.contentLastPos = null; - self.contentStartPos = $.fancybox.getTranslate(self.$content) || { - top: 0, - left: 0 - }; - self.sliderStartPos = $.fancybox.getTranslate($slide); - - // Since position will be absolute, but we need to make it relative to the stage - self.stagePos = $.fancybox.getTranslate(instance.$refs.stage); - - self.sliderStartPos.top -= self.stagePos.top; - self.sliderStartPos.left -= self.stagePos.left; - - self.contentStartPos.top -= self.stagePos.top; - self.contentStartPos.left -= self.stagePos.left; - - $(document) - .off(".fb.touch") - .on(isTouchDevice ? "touchend.fb.touch touchcancel.fb.touch" : "mouseup.fb.touch mouseleave.fb.touch", $.proxy(self, "ontouchend")) - .on(isTouchDevice ? "touchmove.fb.touch" : "mousemove.fb.touch", $.proxy(self, "ontouchmove")); - - if ($.fancybox.isMobile) { - document.addEventListener("scroll", self.onscroll, true); - } - - // Skip if clicked outside the sliding area - if (!(self.opts || self.canPan) || !($target.is(self.$stage) || self.$stage.find($target).length)) { - if ($target.is(".fancybox-image")) { - e.preventDefault(); - } - - if (!($.fancybox.isMobile && $target.parents(".fancybox-caption").length)) { - return; - } - } - - self.isScrollable = isScrollable($target) || isScrollable($target.parent()); - - // Check if element is scrollable and try to prevent default behavior (scrolling) - if (!($.fancybox.isMobile && self.isScrollable)) { - e.preventDefault(); - } - - // One finger or mouse click - swipe or pan an image - if (self.startPoints.length === 1 || current.hasError) { - if (self.canPan) { - $.fancybox.stop(self.$content); - - self.isPanning = true; - } else { - self.isSwiping = true; - } - - self.$container.addClass("fancybox-is-grabbing"); - } - - // Two fingers - zoom image - if (self.startPoints.length === 2 && current.type === "image" && (current.isLoaded || current.$ghost)) { - self.canTap = false; - self.isSwiping = false; - self.isPanning = false; - - self.isZooming = true; - - $.fancybox.stop(self.$content); - - self.centerPointStartX = (self.startPoints[0].x + self.startPoints[1].x) * 0.5 - $(window).scrollLeft(); - self.centerPointStartY = (self.startPoints[0].y + self.startPoints[1].y) * 0.5 - $(window).scrollTop(); - - self.percentageOfImageAtPinchPointX = (self.centerPointStartX - self.contentStartPos.left) / self.contentStartPos.width; - self.percentageOfImageAtPinchPointY = (self.centerPointStartY - self.contentStartPos.top) / self.contentStartPos.height; - - self.startDistanceBetweenFingers = distance(self.startPoints[0], self.startPoints[1]); - } - }; - - Guestures.prototype.onscroll = function (e) { - var self = this; - - self.isScrolling = true; - - document.removeEventListener("scroll", self.onscroll, true); - }; - - Guestures.prototype.ontouchmove = function (e) { - var self = this; - - // Make sure user has not released over iframe or disabled element - if (e.originalEvent.buttons !== undefined && e.originalEvent.buttons === 0) { - self.ontouchend(e); - return; - } - - if (self.isScrolling) { - self.canTap = false; - return; - } - - self.newPoints = getPointerXY(e); - - if (!(self.opts || self.canPan) || !self.newPoints.length || !self.newPoints.length) { - return; - } - - if (!(self.isSwiping && self.isSwiping === true)) { - e.preventDefault(); - } - - self.distanceX = distance(self.newPoints[0], self.startPoints[0], "x"); - self.distanceY = distance(self.newPoints[0], self.startPoints[0], "y"); - - self.distance = distance(self.newPoints[0], self.startPoints[0]); - - // Skip false ontouchmove events (Chrome) - if (self.distance > 0) { - if (self.isSwiping) { - self.onSwipe(e); - } else if (self.isPanning) { - self.onPan(); - } else if (self.isZooming) { - self.onZoom(); - } - } - }; - - Guestures.prototype.onSwipe = function (e) { - var self = this, - instance = self.instance, - swiping = self.isSwiping, - left = self.sliderStartPos.left || 0, - angle; - - // If direction is not yet determined - if (swiping === true) { - // We need at least 10px distance to correctly calculate an angle - if (Math.abs(self.distance) > 10) { - self.canTap = false; - - if (instance.group.length < 2 && self.opts.vertical) { - self.isSwiping = "y"; - } else if (instance.isDragging || self.opts.vertical === false || (self.opts.vertical === "auto" && $(window).width() > 800)) { - self.isSwiping = "x"; - } else { - angle = Math.abs((Math.atan2(self.distanceY, self.distanceX) * 180) / Math.PI); - - self.isSwiping = angle > 45 && angle < 135 ? "y" : "x"; - } - - if (self.isSwiping === "y" && $.fancybox.isMobile && self.isScrollable) { - self.isScrolling = true; - - return; - } - - instance.isDragging = self.isSwiping; - - // Reset points to avoid jumping, because we dropped first swipes to calculate the angle - self.startPoints = self.newPoints; - - $.each(instance.slides, function (index, slide) { - var slidePos, stagePos; - - $.fancybox.stop(slide.$slide); - - slidePos = $.fancybox.getTranslate(slide.$slide); - stagePos = $.fancybox.getTranslate(instance.$refs.stage); - - slide.$slide - .css({ - transform: "", - opacity: "", - "transition-duration": "" - }) - .removeClass("fancybox-animated") - .removeClass(function (index, className) { - return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" "); - }); - - if (slide.pos === instance.current.pos) { - self.sliderStartPos.top = slidePos.top - stagePos.top; - self.sliderStartPos.left = slidePos.left - stagePos.left; - } - - $.fancybox.setTranslate(slide.$slide, { - top: slidePos.top - stagePos.top, - left: slidePos.left - stagePos.left - }); - }); - - // Stop slideshow - if (instance.SlideShow && instance.SlideShow.isActive) { - instance.SlideShow.stop(); - } - } - - return; - } - - // Sticky edges - if (swiping == "x") { - if ( - self.distanceX > 0 && - (self.instance.group.length < 2 || (self.instance.current.index === 0 && !self.instance.current.opts.loop)) - ) { - left = left + Math.pow(self.distanceX, 0.8); - } else if ( - self.distanceX < 0 && - (self.instance.group.length < 2 || - (self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop)) - ) { - left = left - Math.pow(-self.distanceX, 0.8); - } else { - left = left + self.distanceX; - } - } - - self.sliderLastPos = { - top: swiping == "x" ? 0 : self.sliderStartPos.top + self.distanceY, - left: left - }; - - if (self.requestId) { - cancelAFrame(self.requestId); - - self.requestId = null; - } - - self.requestId = requestAFrame(function () { - if (self.sliderLastPos) { - $.each(self.instance.slides, function (index, slide) { - var pos = slide.pos - self.instance.currPos; - - $.fancybox.setTranslate(slide.$slide, { - top: self.sliderLastPos.top, - left: self.sliderLastPos.left + pos * self.canvasWidth + pos * slide.opts.gutter - }); - }); - - self.$container.addClass("fancybox-is-sliding"); - } - }); - }; - - Guestures.prototype.onPan = function () { - var self = this; - - // Prevent accidental movement (sometimes, when tapping casually, finger can move a bit) - if (distance(self.newPoints[0], self.realPoints[0]) < ($.fancybox.isMobile ? 10 : 5)) { - self.startPoints = self.newPoints; - return; - } - - self.canTap = false; - - self.contentLastPos = self.limitMovement(); - - if (self.requestId) { - cancelAFrame(self.requestId); - } - - self.requestId = requestAFrame(function () { - $.fancybox.setTranslate(self.$content, self.contentLastPos); - }); - }; - - // Make panning sticky to the edges - Guestures.prototype.limitMovement = function () { - var self = this; - - var canvasWidth = self.canvasWidth; - var canvasHeight = self.canvasHeight; - - var distanceX = self.distanceX; - var distanceY = self.distanceY; - - var contentStartPos = self.contentStartPos; - - var currentOffsetX = contentStartPos.left; - var currentOffsetY = contentStartPos.top; - - var currentWidth = contentStartPos.width; - var currentHeight = contentStartPos.height; - - var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY, newOffsetX, newOffsetY; - - if (currentWidth > canvasWidth) { - newOffsetX = currentOffsetX + distanceX; - } else { - newOffsetX = currentOffsetX; - } - - newOffsetY = currentOffsetY + distanceY; - - // Slow down proportionally to traveled distance - minTranslateX = Math.max(0, canvasWidth * 0.5 - currentWidth * 0.5); - minTranslateY = Math.max(0, canvasHeight * 0.5 - currentHeight * 0.5); - - maxTranslateX = Math.min(canvasWidth - currentWidth, canvasWidth * 0.5 - currentWidth * 0.5); - maxTranslateY = Math.min(canvasHeight - currentHeight, canvasHeight * 0.5 - currentHeight * 0.5); - - // -> - if (distanceX > 0 && newOffsetX > minTranslateX) { - newOffsetX = minTranslateX - 1 + Math.pow(-minTranslateX + currentOffsetX + distanceX, 0.8) || 0; - } - - // <- - if (distanceX < 0 && newOffsetX < maxTranslateX) { - newOffsetX = maxTranslateX + 1 - Math.pow(maxTranslateX - currentOffsetX - distanceX, 0.8) || 0; - } - - // \/ - if (distanceY > 0 && newOffsetY > minTranslateY) { - newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8) || 0; - } - - // /\ - if (distanceY < 0 && newOffsetY < maxTranslateY) { - newOffsetY = maxTranslateY + 1 - Math.pow(maxTranslateY - currentOffsetY - distanceY, 0.8) || 0; - } - - return { - top: newOffsetY, - left: newOffsetX - }; - }; - - Guestures.prototype.limitPosition = function (newOffsetX, newOffsetY, newWidth, newHeight) { - var self = this; - - var canvasWidth = self.canvasWidth; - var canvasHeight = self.canvasHeight; - - if (newWidth > canvasWidth) { - newOffsetX = newOffsetX > 0 ? 0 : newOffsetX; - newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX; - } else { - // Center horizontally - newOffsetX = Math.max(0, canvasWidth / 2 - newWidth / 2); - } - - if (newHeight > canvasHeight) { - newOffsetY = newOffsetY > 0 ? 0 : newOffsetY; - newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY; - } else { - // Center vertically - newOffsetY = Math.max(0, canvasHeight / 2 - newHeight / 2); - } - - return { - top: newOffsetY, - left: newOffsetX - }; - }; - - Guestures.prototype.onZoom = function () { - var self = this; - - // Calculate current distance between points to get pinch ratio and new width and height - var contentStartPos = self.contentStartPos; - - var currentWidth = contentStartPos.width; - var currentHeight = contentStartPos.height; - - var currentOffsetX = contentStartPos.left; - var currentOffsetY = contentStartPos.top; - - var endDistanceBetweenFingers = distance(self.newPoints[0], self.newPoints[1]); - - var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers; - - var newWidth = Math.floor(currentWidth * pinchRatio); - var newHeight = Math.floor(currentHeight * pinchRatio); - - // This is the translation due to pinch-zooming - var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX; - var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY; - - // Point between the two touches - var centerPointEndX = (self.newPoints[0].x + self.newPoints[1].x) / 2 - $(window).scrollLeft(); - var centerPointEndY = (self.newPoints[0].y + self.newPoints[1].y) / 2 - $(window).scrollTop(); - - // And this is the translation due to translation of the centerpoint - // between the two fingers - var translateFromTranslatingX = centerPointEndX - self.centerPointStartX; - var translateFromTranslatingY = centerPointEndY - self.centerPointStartY; - - // The new offset is the old/current one plus the total translation - var newOffsetX = currentOffsetX + (translateFromZoomingX + translateFromTranslatingX); - var newOffsetY = currentOffsetY + (translateFromZoomingY + translateFromTranslatingY); - - var newPos = { - top: newOffsetY, - left: newOffsetX, - scaleX: pinchRatio, - scaleY: pinchRatio - }; - - self.canTap = false; - - self.newWidth = newWidth; - self.newHeight = newHeight; - - self.contentLastPos = newPos; - - if (self.requestId) { - cancelAFrame(self.requestId); - } - - self.requestId = requestAFrame(function () { - $.fancybox.setTranslate(self.$content, self.contentLastPos); - }); - }; - - Guestures.prototype.ontouchend = function (e) { - var self = this; - - var swiping = self.isSwiping; - var panning = self.isPanning; - var zooming = self.isZooming; - var scrolling = self.isScrolling; - - self.endPoints = getPointerXY(e); - self.dMs = Math.max(new Date().getTime() - self.startTime, 1); - - self.$container.removeClass("fancybox-is-grabbing"); - - $(document).off(".fb.touch"); - - document.removeEventListener("scroll", self.onscroll, true); - - if (self.requestId) { - cancelAFrame(self.requestId); - - self.requestId = null; - } - - self.isSwiping = false; - self.isPanning = false; - self.isZooming = false; - self.isScrolling = false; - - self.instance.isDragging = false; - - if (self.canTap) { - return self.onTap(e); - } - - self.speed = 100; - - // Speed in px/ms - self.velocityX = (self.distanceX / self.dMs) * 0.5; - self.velocityY = (self.distanceY / self.dMs) * 0.5; - - if (panning) { - self.endPanning(); - } else if (zooming) { - self.endZooming(); - } else { - self.endSwiping(swiping, scrolling); - } - - return; - }; - - Guestures.prototype.endSwiping = function (swiping, scrolling) { - var self = this, - ret = false, - len = self.instance.group.length, - distanceX = Math.abs(self.distanceX), - canAdvance = swiping == "x" && len > 1 && ((self.dMs > 130 && distanceX > 10) || distanceX > 50), - speedX = 300; - - self.sliderLastPos = null; - - // Close if swiped vertically / navigate if horizontally - if (swiping == "y" && !scrolling && Math.abs(self.distanceY) > 50) { - // Continue vertical movement - $.fancybox.animate( - self.instance.current.$slide, { - top: self.sliderStartPos.top + self.distanceY + self.velocityY * 150, - opacity: 0 - }, - 200 - ); - ret = self.instance.close(true, 250); - } else if (canAdvance && self.distanceX > 0) { - ret = self.instance.previous(speedX); - } else if (canAdvance && self.distanceX < 0) { - ret = self.instance.next(speedX); - } - - if (ret === false && (swiping == "x" || swiping == "y")) { - self.instance.centerSlide(200); - } - - self.$container.removeClass("fancybox-is-sliding"); - }; - - // Limit panning from edges - // ======================== - Guestures.prototype.endPanning = function () { - var self = this, - newOffsetX, - newOffsetY, - newPos; - - if (!self.contentLastPos) { - return; - } - - if (self.opts.momentum === false || self.dMs > 350) { - newOffsetX = self.contentLastPos.left; - newOffsetY = self.contentLastPos.top; - } else { - // Continue movement - newOffsetX = self.contentLastPos.left + self.velocityX * 500; - newOffsetY = self.contentLastPos.top + self.velocityY * 500; - } - - newPos = self.limitPosition(newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height); - - newPos.width = self.contentStartPos.width; - newPos.height = self.contentStartPos.height; - - $.fancybox.animate(self.$content, newPos, 366); - }; - - Guestures.prototype.endZooming = function () { - var self = this; - - var current = self.instance.current; - - var newOffsetX, newOffsetY, newPos, reset; - - var newWidth = self.newWidth; - var newHeight = self.newHeight; - - if (!self.contentLastPos) { - return; - } - - newOffsetX = self.contentLastPos.left; - newOffsetY = self.contentLastPos.top; - - reset = { - top: newOffsetY, - left: newOffsetX, - width: newWidth, - height: newHeight, - scaleX: 1, - scaleY: 1 - }; - - // Reset scalex/scaleY values; this helps for perfomance and does not break animation - $.fancybox.setTranslate(self.$content, reset); - - if (newWidth < self.canvasWidth && newHeight < self.canvasHeight) { - self.instance.scaleToFit(150); - } else if (newWidth > current.width || newHeight > current.height) { - self.instance.scaleToActual(self.centerPointStartX, self.centerPointStartY, 150); - } else { - newPos = self.limitPosition(newOffsetX, newOffsetY, newWidth, newHeight); - - $.fancybox.animate(self.$content, newPos, 150); - } - }; - - Guestures.prototype.onTap = function (e) { - var self = this; - var $target = $(e.target); - - var instance = self.instance; - var current = instance.current; - - var endPoints = (e && getPointerXY(e)) || self.startPoints; - - var tapX = endPoints[0] ? endPoints[0].x - $(window).scrollLeft() - self.stagePos.left : 0; - var tapY = endPoints[0] ? endPoints[0].y - $(window).scrollTop() - self.stagePos.top : 0; - - var where; - - var process = function (prefix) { - var action = current.opts[prefix]; - - if ($.isFunction(action)) { - action = action.apply(instance, [current, e]); - } - - if (!action) { - return; - } - - switch (action) { - case "close": - instance.close(self.startEvent); - - break; - - case "toggleControls": - instance.toggleControls(); - - break; - - case "next": - instance.next(); - - break; - - case "nextOrClose": - if (instance.group.length > 1) { - instance.next(); - } else { - instance.close(self.startEvent); - } - - break; - - case "zoom": - if (current.type == "image" && (current.isLoaded || current.$ghost)) { - if (instance.canPan()) { - instance.scaleToFit(); - } else if (instance.isScaledDown()) { - instance.scaleToActual(tapX, tapY); - } else if (instance.group.length < 2) { - instance.close(self.startEvent); - } - } - - break; - } - }; - - // Ignore right click - if (e.originalEvent && e.originalEvent.button == 2) { - return; - } - - // Skip if clicked on the scrollbar - if (!$target.is("img") && tapX > $target[0].clientWidth + $target.offset().left) { - return; - } - - // Check where is clicked - if ($target.is(".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container")) { - where = "Outside"; - } else if ($target.is(".fancybox-slide")) { - where = "Slide"; - } else if ( - instance.current.$content && - instance.current.$content - .find($target) - .addBack() - .filter($target).length - ) { - where = "Content"; - } else { - return; - } - - // Check if this is a double tap - if (self.tapped) { - // Stop previously created single tap - clearTimeout(self.tapped); - self.tapped = null; - - // Skip if distance between taps is too big - if (Math.abs(tapX - self.tapX) > 50 || Math.abs(tapY - self.tapY) > 50) { - return this; - } - - // OK, now we assume that this is a double-tap - process("dblclick" + where); - } else { - // Single tap will be processed if user has not clicked second time within 300ms - // or there is no need to wait for double-tap - self.tapX = tapX; - self.tapY = tapY; - - if (current.opts["dblclick" + where] && current.opts["dblclick" + where] !== current.opts["click" + where]) { - self.tapped = setTimeout(function () { - self.tapped = null; - - if (!instance.isAnimating) { - process("click" + where); - } - }, 500); - } else { - process("click" + where); - } - } - - return this; - }; - - $(document) - .on("onActivate.fb", function (e, instance) { - if (instance && !instance.Guestures) { - instance.Guestures = new Guestures(instance); - } - }) - .on("beforeClose.fb", function (e, instance) { - if (instance && instance.Guestures) { - instance.Guestures.destroy(); - } - }); -})(window, document, jQuery); -// ========================================================================== -// -// SlideShow -// Enables slideshow functionality -// -// Example of usage: -// $.fancybox.getInstance().SlideShow.start() -// -// ========================================================================== -(function (document, $) { - "use strict"; - - $.extend(true, $.fancybox.defaults, { - btnTpl: { - slideShow: '" - }, - slideShow: { - autoStart: false, - speed: 3000, - progress: true - } - }); - - var SlideShow = function (instance) { - this.instance = instance; - this.init(); - }; - - $.extend(SlideShow.prototype, { - timer: null, - isActive: false, - $button: null, - - init: function () { - var self = this, - instance = self.instance, - opts = instance.group[instance.currIndex].opts.slideShow; - - self.$button = instance.$refs.toolbar.find("[data-fancybox-play]").on("click", function () { - self.toggle(); - }); - - if (instance.group.length < 2 || !opts) { - self.$button.hide(); - } else if (opts.progress) { - self.$progress = $('
').appendTo(instance.$refs.inner); - } - }, - - set: function (force) { - var self = this, - instance = self.instance, - current = instance.current; - - // Check if reached last element - if (current && (force === true || current.opts.loop || instance.currIndex < instance.group.length - 1)) { - if (self.isActive && current.contentType !== "video") { - if (self.$progress) { - $.fancybox.animate(self.$progress.show(), { - scaleX: 1 - }, current.opts.slideShow.speed); - } - - self.timer = setTimeout(function () { - if (!instance.current.opts.loop && instance.current.index == instance.group.length - 1) { - instance.jumpTo(0); - } else { - instance.next(); - } - }, current.opts.slideShow.speed); - } - } else { - self.stop(); - instance.idleSecondsCounter = 0; - instance.showControls(); - } - }, - - clear: function () { - var self = this; - - clearTimeout(self.timer); - - self.timer = null; - - if (self.$progress) { - self.$progress.removeAttr("style").hide(); - } - }, - - start: function () { - var self = this, - current = self.instance.current; - - if (current) { - self.$button - .attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_STOP) - .removeClass("fancybox-button--play") - .addClass("fancybox-button--pause"); - - self.isActive = true; - - if (current.isComplete) { - self.set(true); - } - - self.instance.trigger("onSlideShowChange", true); - } - }, - - stop: function () { - var self = this, - current = self.instance.current; - - self.clear(); - - self.$button - .attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_START) - .removeClass("fancybox-button--pause") - .addClass("fancybox-button--play"); - - self.isActive = false; - - self.instance.trigger("onSlideShowChange", false); - - if (self.$progress) { - self.$progress.removeAttr("style").hide(); - } - }, - - toggle: function () { - var self = this; - - if (self.isActive) { - self.stop(); - } else { - self.start(); - } - } - }); - - $(document).on({ - "onInit.fb": function (e, instance) { - if (instance && !instance.SlideShow) { - instance.SlideShow = new SlideShow(instance); - } - }, - - "beforeShow.fb": function (e, instance, current, firstRun) { - var SlideShow = instance && instance.SlideShow; - - if (firstRun) { - if (SlideShow && current.opts.slideShow.autoStart) { - SlideShow.start(); - } - } else if (SlideShow && SlideShow.isActive) { - SlideShow.clear(); - } - }, - - "afterShow.fb": function (e, instance, current) { - var SlideShow = instance && instance.SlideShow; - - if (SlideShow && SlideShow.isActive) { - SlideShow.set(); - } - }, - - "afterKeydown.fb": function (e, instance, current, keypress, keycode) { - var SlideShow = instance && instance.SlideShow; - - // "P" or Spacebar - if (SlideShow && current.opts.slideShow && (keycode === 80 || keycode === 32) && !$(document.activeElement).is("button,a,input")) { - keypress.preventDefault(); - - SlideShow.toggle(); - } - }, - - "beforeClose.fb onDeactivate.fb": function (e, instance) { - var SlideShow = instance && instance.SlideShow; - - if (SlideShow) { - SlideShow.stop(); - } - } - }); - - // Page Visibility API to pause slideshow when window is not active - $(document).on("visibilitychange", function () { - var instance = $.fancybox.getInstance(), - SlideShow = instance && instance.SlideShow; - - if (SlideShow && SlideShow.isActive) { - if (document.hidden) { - SlideShow.clear(); - } else { - SlideShow.set(); - } - } - }); -})(document, jQuery); -// ========================================================================== -// -// FullScreen -// Adds fullscreen functionality -// -// ========================================================================== -(function (document, $) { - "use strict"; - - // Collection of methods supported by user browser - var fn = (function () { - var fnMap = [ - ["requestFullscreen", "exitFullscreen", "fullscreenElement", "fullscreenEnabled", "fullscreenchange", "fullscreenerror"], - // new WebKit - [ - "webkitRequestFullscreen", - "webkitExitFullscreen", - "webkitFullscreenElement", - "webkitFullscreenEnabled", - "webkitfullscreenchange", - "webkitfullscreenerror" - ], - // old WebKit (Safari 5.1) - [ - "webkitRequestFullScreen", - "webkitCancelFullScreen", - "webkitCurrentFullScreenElement", - "webkitCancelFullScreen", - "webkitfullscreenchange", - "webkitfullscreenerror" - ], - [ - "mozRequestFullScreen", - "mozCancelFullScreen", - "mozFullScreenElement", - "mozFullScreenEnabled", - "mozfullscreenchange", - "mozfullscreenerror" - ], - ["msRequestFullscreen", "msExitFullscreen", "msFullscreenElement", "msFullscreenEnabled", "MSFullscreenChange", "MSFullscreenError"] - ]; - - var ret = {}; - - for (var i = 0; i < fnMap.length; i++) { - var val = fnMap[i]; - - if (val && val[1] in document) { - for (var j = 0; j < val.length; j++) { - ret[fnMap[0][j]] = val[j]; - } - - return ret; - } - } - - return false; - })(); - - if (fn) { - var FullScreen = { - request: function (elem) { - elem = elem || document.documentElement; - - elem[fn.requestFullscreen](elem.ALLOW_KEYBOARD_INPUT); - }, - exit: function () { - document[fn.exitFullscreen](); - }, - toggle: function (elem) { - elem = elem || document.documentElement; - - if (this.isFullscreen()) { - this.exit(); - } else { - this.request(elem); - } - }, - isFullscreen: function () { - return Boolean(document[fn.fullscreenElement]); - }, - enabled: function () { - return Boolean(document[fn.fullscreenEnabled]); - } - }; - - $.extend(true, $.fancybox.defaults, { - btnTpl: { - fullScreen: '" - }, - fullScreen: { - autoStart: false - } - }); - - $(document).on(fn.fullscreenchange, function () { - var isFullscreen = FullScreen.isFullscreen(), - instance = $.fancybox.getInstance(); - - if (instance) { - // If image is zooming, then force to stop and reposition properly - if (instance.current && instance.current.type === "image" && instance.isAnimating) { - instance.isAnimating = false; - - instance.update(true, true, 0); - - if (!instance.isComplete) { - instance.complete(); - } - } - - instance.trigger("onFullscreenChange", isFullscreen); - - instance.$refs.container.toggleClass("fancybox-is-fullscreen", isFullscreen); - - instance.$refs.toolbar - .find("[data-fancybox-fullscreen]") - .toggleClass("fancybox-button--fsenter", !isFullscreen) - .toggleClass("fancybox-button--fsexit", isFullscreen); - } - }); - } - - $(document).on({ - "onInit.fb": function (e, instance) { - var $container; - - if (!fn) { - instance.$refs.toolbar.find("[data-fancybox-fullscreen]").remove(); - - return; - } - - if (instance && instance.group[instance.currIndex].opts.fullScreen) { - $container = instance.$refs.container; - - $container.on("click.fb-fullscreen", "[data-fancybox-fullscreen]", function (e) { - e.stopPropagation(); - e.preventDefault(); - - FullScreen.toggle(); - }); - - if (instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true) { - FullScreen.request(); - } - - // Expose API - instance.FullScreen = FullScreen; - } else if (instance) { - instance.$refs.toolbar.find("[data-fancybox-fullscreen]").hide(); - } - }, - - "afterKeydown.fb": function (e, instance, current, keypress, keycode) { - // "F" - if (instance && instance.FullScreen && keycode === 70) { - keypress.preventDefault(); - - instance.FullScreen.toggle(); - } - }, - - "beforeClose.fb": function (e, instance) { - if (instance && instance.FullScreen && instance.$refs.container.hasClass("fancybox-is-fullscreen")) { - FullScreen.exit(); - } - } - }); -})(document, jQuery); -// ========================================================================== -// -// Thumbs -// Displays thumbnails in a grid -// -// ========================================================================== -(function (document, $) { - "use strict"; - - var CLASS = "fancybox-thumbs", - CLASS_ACTIVE = CLASS + "-active"; - - // Make sure there are default values - $.fancybox.defaults = $.extend( - true, { - btnTpl: { - thumbs: '" - }, - thumbs: { - autoStart: false, // Display thumbnails on opening - hideOnClose: true, // Hide thumbnail grid when closing animation starts - parentEl: ".fancybox-container", // Container is injected into this element - axis: "y" // Vertical (y) or horizontal (x) scrolling - } - }, - $.fancybox.defaults - ); - - var FancyThumbs = function (instance) { - this.init(instance); - }; - - $.extend(FancyThumbs.prototype, { - $button: null, - $grid: null, - $list: null, - isVisible: false, - isActive: false, - - init: function (instance) { - var self = this, - group = instance.group, - enabled = 0; - - self.instance = instance; - self.opts = group[instance.currIndex].opts.thumbs; - - instance.Thumbs = self; - - self.$button = instance.$refs.toolbar.find("[data-fancybox-thumbs]"); - - // Enable thumbs if at least two group items have thumbnails - for (var i = 0, len = group.length; i < len; i++) { - if (group[i].thumb) { - enabled++; - } - - if (enabled > 1) { - break; - } - } - - if (enabled > 1 && !!self.opts) { - self.$button.removeAttr("style").on("click", function () { - self.toggle(); - }); - - self.isActive = true; - } else { - self.$button.hide(); - } - }, - - create: function () { - var self = this, - instance = self.instance, - parentEl = self.opts.parentEl, - list = [], - src; - - if (!self.$grid) { - // Create main element - self.$grid = $('
').appendTo( - instance.$refs.container - .find(parentEl) - .addBack() - .filter(parentEl) - ); - - // Add "click" event that performs gallery navigation - self.$grid.on("click", "a", function () { - instance.jumpTo($(this).attr("data-index")); - }); - } - - // Build the list - if (!self.$list) { - self.$list = $('
').appendTo(self.$grid); - } - - $.each(instance.group, function (i, item) { - src = item.thumb; - - if (!src && item.type === "image") { - src = item.src; - } - - list.push( - '" - ); - }); - - self.$list[0].innerHTML = list.join(""); - - if (self.opts.axis === "x") { - // Set fixed width for list element to enable horizontal scrolling - self.$list.width( - parseInt(self.$grid.css("padding-right"), 10) + - instance.group.length * - self.$list - .children() - .eq(0) - .outerWidth(true) - ); - } - }, - - focus: function (duration) { - var self = this, - $list = self.$list, - $grid = self.$grid, - thumb, - thumbPos; - - if (!self.instance.current) { - return; - } - - thumb = $list - .children() - .removeClass(CLASS_ACTIVE) - .filter('[data-index="' + self.instance.current.index + '"]') - .addClass(CLASS_ACTIVE); - - thumbPos = thumb.position(); - - // Check if need to scroll to make current thumb visible - if (self.opts.axis === "y" && (thumbPos.top < 0 || thumbPos.top > $list.height() - thumb.outerHeight())) { - $list.stop().animate({ - scrollTop: $list.scrollTop() + thumbPos.top - }, - duration - ); - } else if ( - self.opts.axis === "x" && - (thumbPos.left < $grid.scrollLeft() || thumbPos.left > $grid.scrollLeft() + ($grid.width() - thumb.outerWidth())) - ) { - $list - .parent() - .stop() - .animate({ - scrollLeft: thumbPos.left - }, - duration - ); - } - }, - - update: function () { - var that = this; - that.instance.$refs.container.toggleClass("fancybox-show-thumbs", this.isVisible); - - if (that.isVisible) { - if (!that.$grid) { - that.create(); - } - - that.instance.trigger("onThumbsShow"); - - that.focus(0); - } else if (that.$grid) { - that.instance.trigger("onThumbsHide"); - } - - // Update content position - that.instance.update(); - }, - - hide: function () { - this.isVisible = false; - this.update(); - }, - - show: function () { - this.isVisible = true; - this.update(); - }, - - toggle: function () { - this.isVisible = !this.isVisible; - this.update(); - } - }); - - $(document).on({ - "onInit.fb": function (e, instance) { - var Thumbs; - - if (instance && !instance.Thumbs) { - Thumbs = new FancyThumbs(instance); - - if (Thumbs.isActive && Thumbs.opts.autoStart === true) { - Thumbs.show(); - } - } - }, - - "beforeShow.fb": function (e, instance, item, firstRun) { - var Thumbs = instance && instance.Thumbs; - - if (Thumbs && Thumbs.isVisible) { - Thumbs.focus(firstRun ? 0 : 250); - } - }, - - "afterKeydown.fb": function (e, instance, current, keypress, keycode) { - var Thumbs = instance && instance.Thumbs; - - // "G" - if (Thumbs && Thumbs.isActive && keycode === 71) { - keypress.preventDefault(); - - Thumbs.toggle(); - } - }, - - "beforeClose.fb": function (e, instance) { - var Thumbs = instance && instance.Thumbs; - - if (Thumbs && Thumbs.isVisible && Thumbs.opts.hideOnClose !== false) { - Thumbs.$grid.hide(); - } - } - }); -})(document, jQuery); -//// ========================================================================== -// -// Share -// Displays simple form for sharing current url -// -// ========================================================================== -(function (document, $) { - "use strict"; - - $.extend(true, $.fancybox.defaults, { - btnTpl: { - share: '" - }, - share: { - url: function (instance, item) { - return ( - (!instance.currentHash && !(item.type === "inline" || item.type === "html") ? item.origSrc || item.src : false) || window.location - ); - }, - tpl: '
' + - "

{{SHARE}}

" + - "

" + - '' + - '' + - "Facebook" + - "" + - '' + - '' + - "Twitter" + - "" + - '' + - '' + - "Pinterest" + - "" + - "

" + - '

' + - "
" - } - }); - - function escapeHtml(string) { - var entityMap = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'", - "/": "/", - "`": "`", - "=": "=" - }; - - return String(string).replace(/[&<>"'`=\/]/g, function (s) { - return entityMap[s]; - }); - } - - $(document).on("click", "[data-fancybox-share]", function () { - var instance = $.fancybox.getInstance(), - current = instance.current || null, - url, - tpl; - - if (!current) { - return; - } - - if ($.type(current.opts.share.url) === "function") { - url = current.opts.share.url.apply(current, [instance, current]); - } - - tpl = current.opts.share.tpl - .replace(/\{\{media\}\}/g, current.type === "image" ? encodeURIComponent(current.src) : "") - .replace(/\{\{url\}\}/g, encodeURIComponent(url)) - .replace(/\{\{url_raw\}\}/g, escapeHtml(url)) - .replace(/\{\{descr\}\}/g, instance.$caption ? encodeURIComponent(instance.$caption.text()) : ""); - - $.fancybox.open({ - src: instance.translate(instance, tpl), - type: "html", - opts: { - touch: false, - animationEffect: false, - afterLoad: function (shareInstance, shareCurrent) { - // Close self if parent instance is closing - instance.$refs.container.one("beforeClose.fb", function () { - shareInstance.close(null, 0); - }); - - // Opening links in a popup window - shareCurrent.$content.find(".fancybox-share__button").click(function () { - window.open(this.href, "Share", "width=550, height=450"); - return false; - }); - }, - mobile: { - autoFocus: false - } - } - }); - }); -})(document, jQuery); -// ========================================================================== -// -// Hash -// Enables linking to each modal -// -// ========================================================================== -(function (window, document, $) { - "use strict"; - - // Simple $.escapeSelector polyfill (for jQuery prior v3) - if (!$.escapeSelector) { - $.escapeSelector = function (sel) { - var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g; - var fcssescape = function (ch, asCodePoint) { - if (asCodePoint) { - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if (ch === "\0") { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice(0, -1) + "\\" + ch.charCodeAt(ch.length - 1).toString(16) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }; - - return (sel + "").replace(rcssescape, fcssescape); - }; - } - - // Get info about gallery name and current index from url - function parseUrl() { - var hash = window.location.hash.substr(1), - rez = hash.split("-"), - index = rez.length > 1 && /^\+?\d+$/.test(rez[rez.length - 1]) ? parseInt(rez.pop(-1), 10) || 1 : 1, - gallery = rez.join("-"); - - return { - hash: hash, - /* Index is starting from 1 */ - index: index < 1 ? 1 : index, - gallery: gallery - }; - } - - // Trigger click evnt on links to open new fancyBox instance - function triggerFromUrl(url) { - if (url.gallery !== "") { - // If we can find element matching 'data-fancybox' atribute, - // then triggering click event should start fancyBox - $("[data-fancybox='" + $.escapeSelector(url.gallery) + "']") - .eq(url.index - 1) - .focus() - .trigger("click.fb-start"); - } - } - - // Get gallery name from current instance - function getGalleryID(instance) { - var opts, ret; - - if (!instance) { - return false; - } - - opts = instance.current ? instance.current.opts : instance.opts; - ret = opts.hash || (opts.$orig ? opts.$orig.data("fancybox") || opts.$orig.data("fancybox-trigger") : ""); - - return ret === "" ? false : ret; - } - - // Start when DOM becomes ready - $(function () { - // Check if user has disabled this module - if ($.fancybox.defaults.hash === false) { - return; - } - - // Update hash when opening/closing fancyBox - $(document).on({ - "onInit.fb": function (e, instance) { - var url, gallery; - - if (instance.group[instance.currIndex].opts.hash === false) { - return; - } - - url = parseUrl(); - gallery = getGalleryID(instance); - - // Make sure gallery start index matches index from hash - if (gallery && url.gallery && gallery == url.gallery) { - instance.currIndex = url.index - 1; - } - }, - - "beforeShow.fb": function (e, instance, current, firstRun) { - var gallery; - - if (!current || current.opts.hash === false) { - return; - } - - // Check if need to update window hash - gallery = getGalleryID(instance); - - if (!gallery) { - return; - } - - // Variable containing last hash value set by fancyBox - // It will be used to determine if fancyBox needs to close after hash change is detected - instance.currentHash = gallery + (instance.group.length > 1 ? "-" + (current.index + 1) : ""); - - // If current hash is the same (this instance most likely is opened by hashchange), then do nothing - if (window.location.hash === "#" + instance.currentHash) { - return; - } - - if (firstRun && !instance.origHash) { - instance.origHash = window.location.hash; - } - - if (instance.hashTimer) { - clearTimeout(instance.hashTimer); - } - - // Update hash - instance.hashTimer = setTimeout(function () { - if ("replaceState" in window.history) { - window.history[firstRun ? "pushState" : "replaceState"]({}, - document.title, - window.location.pathname + window.location.search + "#" + instance.currentHash - ); - - if (firstRun) { - instance.hasCreatedHistory = true; - } - } else { - window.location.hash = instance.currentHash; - } - - instance.hashTimer = null; - }, 300); - }, - - "beforeClose.fb": function (e, instance, current) { - if (!current || current.opts.hash === false) { - return; - } - - clearTimeout(instance.hashTimer); - - // Goto previous history entry - if (instance.currentHash && instance.hasCreatedHistory) { - window.history.back(); - } else if (instance.currentHash) { - if ("replaceState" in window.history) { - window.history.replaceState({}, document.title, window.location.pathname + window.location.search + (instance.origHash || "")); - } else { - window.location.hash = instance.origHash; - } - } - - instance.currentHash = null; - } - }); - - // Check if need to start/close after url has changed - $(window).on("hashchange.fb", function () { - var url = parseUrl(), - fb = null; - - // Find last fancyBox instance that has "hash" - $.each( - $(".fancybox-container") - .get() - .reverse(), - function (index, value) { - var tmp = $(value).data("FancyBox"); - - if (tmp && tmp.currentHash) { - fb = tmp; - return false; - } - } - ); - - if (fb) { - // Now, compare hash values - if (fb.currentHash !== url.gallery + "-" + url.index && !(url.index === 1 && fb.currentHash == url.gallery)) { - fb.currentHash = null; - - fb.close(); - } - } else if (url.gallery !== "") { - triggerFromUrl(url); - } - }); - - // Check current hash and trigger click event on matching element to start fancyBox, if needed - setTimeout(function () { - if (!$.fancybox.getInstance()) { - triggerFromUrl(parseUrl()); - } - }, 50); - }); -})(window, document, jQuery); -// ========================================================================== -// -// Wheel -// Basic mouse weheel support for gallery navigation -// -// ========================================================================== -(function (document, $) { - "use strict"; - - var prevTime = new Date().getTime(); - - $(document).on({ - "onInit.fb": function (e, instance, current) { - instance.$refs.stage.on("mousewheel DOMMouseScroll wheel MozMousePixelScroll", function (e) { - var current = instance.current, - currTime = new Date().getTime(); - - if (instance.group.length < 2 || current.opts.wheel === false || (current.opts.wheel === "auto" && current.type !== "image")) { - return; - } - - e.preventDefault(); - e.stopPropagation(); - - if (current.$slide.hasClass("fancybox-animated")) { - return; - } - - e = e.originalEvent || e; - - if (currTime - prevTime < 250) { - return; - } - - prevTime = currTime; - - instance[(-e.deltaY || -e.deltaX || e.wheelDelta || -e.detail) < 0 ? "next" : "previous"](); - }); - } - }); -})(document, jQuery); - -/***/ }), - -/***/ "./src/forum/index.js": -/*!****************************!*\ - !*** ./src/forum/index.js ***! - \****************************/ -/*! no exports provided */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var flarum_extend__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! flarum/extend */ "flarum/extend"); -/* harmony import */ var flarum_extend__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(flarum_extend__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var flarum_components_CommentPost__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! flarum/components/CommentPost */ "flarum/components/CommentPost"); -/* harmony import */ var flarum_components_CommentPost__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(flarum_components_CommentPost__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var flarum_components_ModalManager__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! flarum/components/ModalManager */ "flarum/components/ModalManager"); -/* harmony import */ var flarum_components_ModalManager__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(flarum_components_ModalManager__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _fancyapps_fancybox__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @fancyapps/fancybox */ "./node_modules/@fancyapps/fancybox/dist/jquery.fancybox.js"); -/* harmony import */ var _fancyapps_fancybox__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_fancyapps_fancybox__WEBPACK_IMPORTED_MODULE_3__); -/* - * FancyBox Extension for Flarum - * Copyright (C) 2019 Eleanor Hawk - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - - - - - -function categorizeImages(element) { - var imageWrapperHtml = '
'; - var badgeHtml = "\n "; - - var captionHtml = function captionHtml(caption) { - return "\n
\n " + caption + "\n
\n "; - }; - - $(element).find('p, th, td').children('img:not([class]):not([data-nothing-fancy])').each(function (i, e) { - var caption = $(e).attr('title') || ''; - - if ($(e).parent().contents().length === 1) { - $(e).addClass('block-image'); - $(e).wrap('' + imageWrapperHtml + ''); - } else { - $(e).addClass('inline-image'); - $(e).wrap('' + imageWrapperHtml + ''); - } - - $(e).parent().append(badgeHtml); - if (caption !== '') $(e).closest('a').append(captionHtml(caption)); - }); - $(element).find('p, th, td').find("a:not(\n .block-image-link,\n .inline-image-link,\n .block-image-self-link,\n .inline-image-self-link\n ) > img:not([class])").each(function (i, e) { - var link = $(e).parent(); - - if (typeof $(e).data('nothing-fancy') !== 'undefined' && !(link.hasClass('fancybox--iframe-link') || link.hasClass('fancybox--video-link'))) { - return true; - } - - var caption = $(e).attr('title') || link.attr('title') || ''; - - if (link.contents().length === 1 && link.parent().contents().length === 1) { - $(e).addClass('block-image'); - - if ($(e).attr('src') !== link.attr('href')) { - link.addClass('block-image-link'); - } else { - link.addClass('block-image-self-link'); - } - } else { - $(e).addClass('inline-image'); - - if ($(e).attr('src') !== link.attr('href')) { - link.addClass('inline-image-link'); - } else { - link.addClass('inline-image-self-link'); - } - } - - link.append(badgeHtml); - link.wrapInner(imageWrapperHtml); - if (caption !== '') link.append(captionHtml(caption)); - }); -} - -app.initializers.add('the-turk-fancybox', function (app) { - $.fancybox.defaults.toolbar = false; - $.fancybox.defaults.smallBtn = true; - $.fancybox.defaults.lang = app.translator.locale; - $.fancybox.defaults.i18n[app.translator.locale] = { - NEXT: app.translator.trans('the-turk-fancybox.forum.next'), - PREV: app.translator.trans('the-turk-fancybox.forum.prev'), - CLOSE: app.translator.trans('the-turk-fancybox.forum.close'), - ERROR: app.translator.trans('the-turk-fancybox.forum.error') - }; - var selectors = "\n a.block-image-self-link,\n a.inline-image-self-link,\n a.fancybox--iframe-link,\n a.fancybox--video-link\n "; - Object(flarum_extend__WEBPACK_IMPORTED_MODULE_0__["extend"])(flarum_components_CommentPost__WEBPACK_IMPORTED_MODULE_1___default.a.prototype, 'config', function (x, isInitialized, context) { - var _this = this; - - categorizeImages(this.element); - $(this.element).find(selectors).click(function (e) { - return e.preventDefault(); - }); - - if (!this.isEditing() && !('fancybox_gallery' in this)) { - var fancies = $(this.element).find(selectors).not("\n a.block-image-link *,\n a.inline-image-link *"); - var gallery = fancies.map(function (i, e) { - var type; - var caption = $(e).find('img').attr('title') || $(e).attr('title') || ''; - var src = $(e).attr('href') || $(e).find('img').attr('src'); - - if ($(e).hasClass('fancybox--iframe-link')) { - type = 'iframe'; - } else if (!$(e).hasClass('fancybox--video-link')) { - type = 'image'; - } - - return { - src: src, - type: type, - opts: { - caption: caption - } - }; - }); - this.fancybox_gallery = gallery.length ? gallery : false; - - if (this.fancybox_gallery) { - fancies.each(function (i, e) { - var index = i; - $(e).off('click.fancybox'); - $(e).on('click.fancybox', function (event) { - $.fancybox.open(_this.fancybox_gallery, {}, index); - }); - }); - } - } else if (this.isEditing() && 'fancybox_gallery' in this) { - delete this.fancybox_gallery; - } - }); - Object(flarum_extend__WEBPACK_IMPORTED_MODULE_0__["extend"])(flarum_components_ModalManager__WEBPACK_IMPORTED_MODULE_2___default.a.prototype, 'show', function (x) { - $.fancybox.close(); - }); - - if (s9e && s9e.TextFormatter) { - Object(flarum_extend__WEBPACK_IMPORTED_MODULE_0__["extend"])(s9e.TextFormatter, 'preview', function (x, preview, element) { - if (element.matches('.Post *')) categorizeImages(element); - }); - } -}); - -/***/ }), - -/***/ "flarum/components/CommentPost": -/*!***************************************************************!*\ - !*** external "flarum.core.compat['components/CommentPost']" ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -module.exports = flarum.core.compat['components/CommentPost']; - -/***/ }), - -/***/ "flarum/components/ModalManager": -/*!****************************************************************!*\ - !*** external "flarum.core.compat['components/ModalManager']" ***! - \****************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -module.exports = flarum.core.compat['components/ModalManager']; - -/***/ }), - -/***/ "flarum/extend": -/*!***********************************************!*\ - !*** external "flarum.core.compat['extend']" ***! - \***********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -module.exports = flarum.core.compat['extend']; - -/***/ }) - -/******/ }); +module.exports=function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=1)}([function(e,n){app.initializers.add("malago/flancy",(function(){console.log("[malago/flancy] Hello, forum!")}))},function(e,n,t){"use strict";t.r(n);var r=t(0);for(var o in r)["default"].indexOf(o)<0&&function(e){t.d(n,e,(function(){return r[e]}))}(o)}]); //# sourceMappingURL=forum.js.map \ No newline at end of file diff --git a/js/dist/forum.js.map b/js/dist/forum.js.map index 65725e4..2a938fe 100644 --- a/js/dist/forum.js.map +++ b/js/dist/forum.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack://@the-turk/fancybox/webpack/bootstrap","webpack://@the-turk/fancybox/./forum.js","webpack://@the-turk/fancybox/./node_modules/@fancyapps/fancybox/dist/jquery.fancybox.js","webpack://@the-turk/fancybox/./src/forum/index.js","webpack://@the-turk/fancybox/external \"flarum.core.compat['components/CommentPost']\"","webpack://@the-turk/fancybox/external \"flarum.core.compat['components/ModalManager']\"","webpack://@the-turk/fancybox/external \"flarum.core.compat['extend']\""],"names":["categorizeImages","element","imageWrapperHtml","badgeHtml","captionHtml","caption","$","find","children","each","i","e","attr","parent","contents","length","addClass","wrap","append","closest","link","data","hasClass","wrapInner","app","initializers","add","fancybox","defaults","toolbar","smallBtn","lang","translator","locale","i18n","NEXT","trans","PREV","CLOSE","ERROR","selectors","extend","CommentPost","prototype","x","isInitialized","context","click","preventDefault","isEditing","fancies","not","gallery","map","type","src","opts","fancybox_gallery","index","off","on","event","open","ModalManager","close","s9e","TextFormatter","preview","matches"],"mappings":";;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;;AClFA;AAAA;AAAA,wC;;;;;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA,uCAAuC,IAAI,uBAAuB,IAAI,4EAA4E;;AAElJ;AACA;AACA;AACA;;AAEA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA,uFAAuF,QAAQ;AAC/F,wBAAwB,KAAK,UAAU,QAAQ;AAC/C,0EAA0E,KAAK;AAC/E;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,4EAA4E,OAAO;AACnF,uCAAuC,SAAS;AAChD,0CAA0C,QAAQ;AAClD;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,gDAAgD,OAAO;;AAEvD;AACA,+GAA+G,UAAU,oBAAoB;AAC7I;AACA;;AAEA,+FAA+F,MAAM;AACrG;AACA;;AAEA,kGAAkG,OAAO;AACzG;AACA;;AAEA;AACA,0GAA0G,MAAM;AAChH;AACA;;AAEA,4GAA4G,MAAM;AAClH;AACA;;AAEA;AACA;AACA,iHAAiH,OAAO;AACxH;AACA;AACA,KAAK;;AAEL;AACA;;AAEA,wCAAwC;AACxC;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,6BAA6B;AAC7B;AACA,wBAAwB;AACxB,2GAA2G;AAC3G;AACA;AACA;AACA;AACA;AACA;AACA,0BAA0B,OAAO;AACjC;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,+BAA+B;;AAE/B;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yFAAyF;AACzF;AACA,eAAe;AACf;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA,wBAAwB,SAAS;AACjC,wBAAwB,QAAQ;AAChC;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,OAAO;;AAEP;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;;AAEA,4BAA4B,EAAE,OAAO,EAAE;AACvC;AACA,OAAO;AACP,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,oBAAoB;AACpB,mBAAmB;AACnB;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,iCAAiC,oCAAoC;;AAErE;AACA;AACA,SAAS;AACT;AACA;;AAEA,qDAAqD,gBAAgB;AACrE;AACA,kCAAkC;;AAElC;AACA;;AAEA;;AAEA;AACA,+CAA+C,GAAG;AAClD;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oCAAoC;;AAEpC;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW;AACX;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,WAAW;AACX;AACA;AACA;;AAEA;AACA;AACA,SAAS;AACT;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;;AAEA;AACA;;AAEA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA,SAAS;AACT;AACA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,aAAa;AACb;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,SAAS;AACT;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,6CAA6C;AAC7C;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW;;AAEX;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW;;AAEX;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA,4CAA4C;AAC5C;AACA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;AACA;AACA,OAAO;AACP,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;;AAEX;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,wBAAwB,EAAE,KAAK,EAAE;AACjC,wBAAwB,QAAQ;AAChC,wBAAwB,QAAQ;AAChC;;AAEA;;AAEA;AACA;AACA;AACA,WAAW;AACX;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA,uBAAuB;AACvB;AACA;AACA;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;;AAEA;AACA;AACA,WAAW;;AAEX;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA,SAAS;;AAET;AACA;AACA;AACA,SAAS;;AAET;AACA,uBAAuB,iBAAiB;AACxC;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;AACT;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;;AAEA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA,sDAAsD,KAAK;AAC3D;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA,SAAS;;AAET;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW;;AAEX;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA,SAAS;AACT,OAAO;AACP;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;;AAET;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,SAAS;;AAET;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,SAAS;AACT;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA,SAAS;;AAET;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA,8EAA8E;;AAE9E;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;;AAEX;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA,mBAAmB;AACnB;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,WAAW;AACX;;AAEA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;;AAEA;AACA,WAAW;AACX;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA,OAAO;;AAEP;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,OAAO;;AAEP;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,SAAS;;AAET;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,OAAO;AACP;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA,OAAO;AACP;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,6BAA6B;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;AACT;AACA;;AAEA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA,SAAS;AACT;AACA;;AAEA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,OAAO;AACP;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,kIAAkI,GAAG;AACrI;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA,wCAAwC,IAAI,SAAS,EAAE;AACvD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,wCAAwC,IAAI,SAAS,EAAE;AACvD;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,6BAA6B;;AAE7B;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA,uBAAuB,sBAAsB;AAC7C;;AAEA;AACA;AACA;AACA;AACA;;AAEA,gCAAgC;;AAEhC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;;AAEA;AACA,KAAK;;AAEL;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;AACT;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;;AAEA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX,SAAS;AACT;;AAEA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;AACA;AACA,SAAS;AACT;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,8DAA8D,OAAO;AACrE;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,OAAO;AACP;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,SAAS;AACT;AACA,SAAS;AACT;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW;AACX,SAAS;;AAET;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW;AACX,SAAS;;AAET;AACA;AACA,KAAK;AACL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA,KAAK;AACL;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;AACL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,kCAAkC;AAClC;;AAEA;AACA;AACA,KAAK;AACL;AACA,KAAK;AACL;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,WAAW;AACX;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA,aAAa;AACb;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oGAAoG,YAAY;AAChH;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,OAAO;;AAEP;AACA;AACA,OAAO;AACP;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;;AAEA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,WAAW;AACX;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,GAAG;AACH,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,mBAAmB,kBAAkB;AACrC;;AAEA;AACA,uBAAuB,gBAAgB;AACvC;AACA;;AAEA;AACA;AACA;;AAEA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;;AAEA;AACA;AACA,SAAS;AACT;AACA;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;;AAEA;AACA;AACA,gHAAgH,aAAa;AAC7H;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,SAAS;;AAET;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,GAAG;AACH,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,uGAAuG,QAAQ;AAC/G;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;;AAEA;AACA,yCAAyC,SAAS;AAClD;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;;AAET;AACA,OAAO;AACP;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAS;AACT;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,gCAAgC;AAChC;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,OAAO;AACP;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;AACH,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,kGAAkG,OAAO;AACzG;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,eAAe,OAAO;AACtB;AACA,2HAA2H,KAAK;AAChI;AACA;AACA;AACA,mHAAmH,KAAK,QAAQ,OAAO;AACvI;AACA;AACA;AACA,+HAA+H,KAAK,eAAe,OAAO,SAAS,OAAO;AAC1K;AACA;AACA;AACA;AACA,sEAAsE,SAAS;AAC/E;AACA;AACA,GAAG;;AAEH;AACA;AACA,iBAAiB;AACjB,gBAAgB;AAChB,gBAAgB;AAChB,kBAAkB;AAClB,iBAAiB;AACjB,kBAAkB;AAClB,kBAAkB;AAClB,kBAAkB;AAClB;;AAEA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,kBAAkB,EAAE,OAAO,EAAE;AAC7B,kBAAkB,EAAE,KAAK,EAAE;AAC3B,kBAAkB,EAAE,SAAS,EAAE;AAC/B,kBAAkB,EAAE,OAAO,EAAE;;AAE7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;;AAEX;AACA;AACA;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,sEAAsE;AACtE;AACA;AACA;;AAEA;AACA;AACA;AACA,WAAW;AACX;AACA;;AAEA;AACA,SAAS;AACT,OAAO;;AAEP;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,SAAS;AACT;AACA,0CAA0C;AAC1C,WAAW;AACX;AACA;AACA;;AAEA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,OAAO;AACP;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA,OAAO;AACP;AACA,GAAG;AACH,CAAC,oB;;;;;;;;;;;;AC//KD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;;;;;;;;;AAeA;AACA;AACA;AACA;;AAEA,SAASA,gBAAT,CAA0BC,OAA1B,EAAmC;AACjC,MAAMC,gBAAgB,GAAG,mCAAzB;AACA,MAAMC,SAAS,yEAAf;;AAIA,MAAIC,WAAW,GAAG,SAAdA,WAAc,CAAUC,OAAV,EAAmB;AACnC,WAAO,4DAEOA,OAFP,gCAAP;AAKD,GAND;;AAQAC,GAAC,CAACL,OAAD,CAAD,CAAWM,IAAX,CAAgB,WAAhB,EAA6BC,QAA7B,CAAsC,4CAAtC,EAAoFC,IAApF,CAAyF,UAACC,CAAD,EAAIC,CAAJ,EAAU;AACjG,QAAIN,OAAO,GAAGC,CAAC,CAACK,CAAD,CAAD,CAAKC,IAAL,CAAU,OAAV,KAAsB,EAApC;;AAEA,QAAIN,CAAC,CAACK,CAAD,CAAD,CAAKE,MAAL,GAAcC,QAAd,GAAyBC,MAAzB,KAAoC,CAAxC,EAA2C;AACzCT,OAAC,CAACK,CAAD,CAAD,CAAKK,QAAL,CAAc,aAAd;AACAV,OAAC,CAACK,CAAD,CAAD,CAAKM,IAAL,CAAU,oDAAoDf,gBAApD,GAAuE,MAAjF;AACD,KAHD,MAGO;AACLI,OAAC,CAACK,CAAD,CAAD,CAAKK,QAAL,CAAc,cAAd;AACAV,OAAC,CAACK,CAAD,CAAD,CAAKM,IAAL,CAAU,qDAAqDf,gBAArD,GAAwE,MAAlF;AACD;;AAEDI,KAAC,CAACK,CAAD,CAAD,CAAKE,MAAL,GAAcK,MAAd,CAAqBf,SAArB;AACA,QAAIE,OAAO,KAAK,EAAhB,EAAoBC,CAAC,CAACK,CAAD,CAAD,CAAKQ,OAAL,CAAa,GAAb,EAAkBD,MAAlB,CAAyBd,WAAW,CAACC,OAAD,CAApC;AACrB,GAbD;AAeAC,GAAC,CAACL,OAAD,CAAD,CAAWM,IAAX,CAAgB,WAAhB,EAA6BA,IAA7B,wJAKyBE,IALzB,CAK8B,UAACC,CAAD,EAAIC,CAAJ,EAAU;AACtC,QAAIS,IAAI,GAAGd,CAAC,CAACK,CAAD,CAAD,CAAKE,MAAL,EAAX;;AAEA,QAAI,OAAOP,CAAC,CAACK,CAAD,CAAD,CAAKU,IAAL,CAAU,eAAV,CAAP,KAAsC,WAAtC,IACK,EAAED,IAAI,CAACE,QAAL,CAAc,uBAAd,KAA0CF,IAAI,CAACE,QAAL,CAAc,sBAAd,CAA5C,CADT,EAC6F;AAC5F,aAAO,IAAP;AACA;;AAED,QAAIjB,OAAO,GAAGC,CAAC,CAACK,CAAD,CAAD,CAAKC,IAAL,CAAU,OAAV,KAAsBQ,IAAI,CAACR,IAAL,CAAU,OAAV,CAAtB,IAA4C,EAA1D;;AAEA,QAAIQ,IAAI,CAACN,QAAL,GAAgBC,MAAhB,KAA2B,CAA3B,IACCK,IAAI,CAACP,MAAL,GAAcC,QAAd,GAAyBC,MAAzB,KAAoC,CADzC,EAC4C;AAC1CT,OAAC,CAACK,CAAD,CAAD,CAAKK,QAAL,CAAc,aAAd;;AACA,UAAIV,CAAC,CAACK,CAAD,CAAD,CAAKC,IAAL,CAAU,KAAV,MAAqBQ,IAAI,CAACR,IAAL,CAAU,MAAV,CAAzB,EAA4C;AAC1CQ,YAAI,CAACJ,QAAL,CAAc,kBAAd;AACD,OAFD,MAEO;AACLI,YAAI,CAACJ,QAAL,CAAc,uBAAd;AACD;AACF,KARD,MAQO;AACLV,OAAC,CAACK,CAAD,CAAD,CAAKK,QAAL,CAAc,cAAd;;AACA,UAAIV,CAAC,CAACK,CAAD,CAAD,CAAKC,IAAL,CAAU,KAAV,MAAqBQ,IAAI,CAACR,IAAL,CAAU,MAAV,CAAzB,EAA4C;AAC1CQ,YAAI,CAACJ,QAAL,CAAc,mBAAd;AACD,OAFD,MAEO;AACLI,YAAI,CAACJ,QAAL,CAAc,wBAAd;AACD;AACF;;AAEDI,QAAI,CAACF,MAAL,CAAYf,SAAZ;AACAiB,QAAI,CAACG,SAAL,CAAerB,gBAAf;AACA,QAAIG,OAAO,KAAK,EAAhB,EAAoBe,IAAI,CAACF,MAAL,CAAYd,WAAW,CAACC,OAAD,CAAvB;AACrB,GAnCD;AAoCD;;AAEDmB,GAAG,CAACC,YAAJ,CAAiBC,GAAjB,CAAqB,mBAArB,EAA0C,UAAAF,GAAG,EAAI;AAC/ClB,GAAC,CAACqB,QAAF,CAAWC,QAAX,CAAoBC,OAApB,GAA8B,KAA9B;AACAvB,GAAC,CAACqB,QAAF,CAAWC,QAAX,CAAoBE,QAApB,GAA+B,IAA/B;AACAxB,GAAC,CAACqB,QAAF,CAAWC,QAAX,CAAoBG,IAApB,GAA2BP,GAAG,CAACQ,UAAJ,CAAeC,MAA1C;AACA3B,GAAC,CAACqB,QAAF,CAAWC,QAAX,CAAoBM,IAApB,CAAyBV,GAAG,CAACQ,UAAJ,CAAeC,MAAxC,IAAkD;AAChDE,QAAI,EAAEX,GAAG,CAACQ,UAAJ,CAAeI,KAAf,CAAqB,8BAArB,CAD0C;AAEhDC,QAAI,EAAEb,GAAG,CAACQ,UAAJ,CAAeI,KAAf,CAAqB,8BAArB,CAF0C;AAGhDE,SAAK,EAAEd,GAAG,CAACQ,UAAJ,CAAeI,KAAf,CAAqB,+BAArB,CAHyC;AAIhDG,SAAK,EAAEf,GAAG,CAACQ,UAAJ,CAAeI,KAAf,CAAqB,+BAArB;AAJyC,GAAlD;AAOA,MAAMI,SAAS,gIAAf;AAOAC,8DAAM,CAACC,oEAAW,CAACC,SAAb,EAAwB,QAAxB,EAAkC,UAASC,CAAT,EAAYC,aAAZ,EAA2BC,OAA3B,EAAoC;AAAA;;AAC1E9C,oBAAgB,CAAC,KAAKC,OAAN,CAAhB;AAIAK,KAAC,CAAC,KAAKL,OAAN,CAAD,CAAgBM,IAAhB,CAAqBiC,SAArB,EAAgCO,KAAhC,CAAsC,UAACpC,CAAD;AAAA,aAAOA,CAAC,CAACqC,cAAF,EAAP;AAAA,KAAtC;;AAEA,QAAI,CAAC,KAAKC,SAAL,EAAD,IAAqB,EAAE,sBAAsB,IAAxB,CAAzB,EAAwD;AACtD,UAAIC,OAAO,GAAG5C,CAAC,CAAC,KAAKL,OAAN,CAAD,CAAgBM,IAAhB,CAAqBiC,SAArB,EAAgCW,GAAhC,kEAAd;AAKA,UAAIC,OAAO,GAAGF,OAAO,CAACG,GAAR,CAAY,UAAC3C,CAAD,EAAIC,CAAJ,EAAU;AAClC,YAAI2C,IAAJ;AACA,YAAIjD,OAAO,GAAGC,CAAC,CAACK,CAAD,CAAD,CAAKJ,IAAL,CAAU,KAAV,EAAiBK,IAAjB,CAAsB,OAAtB,KAAkCN,CAAC,CAACK,CAAD,CAAD,CAAKC,IAAL,CAAU,OAAV,CAAlC,IAAwD,EAAtE;AACA,YAAI2C,GAAG,GAAGjD,CAAC,CAACK,CAAD,CAAD,CAAKC,IAAL,CAAU,MAAV,KAAqBN,CAAC,CAACK,CAAD,CAAD,CAAKJ,IAAL,CAAU,KAAV,EAAiBK,IAAjB,CAAsB,KAAtB,CAA/B;;AAEA,YAAIN,CAAC,CAACK,CAAD,CAAD,CAAKW,QAAL,CAAc,uBAAd,CAAJ,EAA4C;AAC1CgC,cAAI,GAAG,QAAP;AACD,SAFD,MAEO,IAAI,CAAChD,CAAC,CAACK,CAAD,CAAD,CAAKW,QAAL,CAAc,sBAAd,CAAL,EAA4C;AACjDgC,cAAI,GAAG,OAAP;AACD;;AAED,eAAO;AACLC,aAAG,EAAEA,GADA;AAELD,cAAI,EAAEA,IAFD;AAGLE,cAAI,EAAG;AACLnD,mBAAO,EAAGA;AADL;AAHF,SAAP;AAOD,OAlBa,CAAd;AAoBA,WAAKoD,gBAAL,GAAwBL,OAAO,CAACrC,MAAR,GAAiBqC,OAAjB,GAA2B,KAAnD;;AAEA,UAAI,KAAKK,gBAAT,EAA2B;AACzBP,eAAO,CAACzC,IAAR,CAAa,UAACC,CAAD,EAAIC,CAAJ,EAAU;AACrB,cAAI+C,KAAK,GAAGhD,CAAZ;AAEAJ,WAAC,CAACK,CAAD,CAAD,CAAKgD,GAAL,CAAS,gBAAT;AACArD,WAAC,CAACK,CAAD,CAAD,CAAKiD,EAAL,CAAQ,gBAAR,EAA0B,UAACC,KAAD,EAAW;AACnCvD,aAAC,CAACqB,QAAF,CAAWmC,IAAX,CAAgB,KAAI,CAACL,gBAArB,EAAuC,EAAvC,EAA2CC,KAA3C;AACD,WAFD;AAGD,SAPD;AAQD;AACF,KAtCD,MAsCO,IAAI,KAAKT,SAAL,MAAoB,sBAAsB,IAA9C,EAAoD;AACzD,aAAO,KAAKQ,gBAAZ;AACD;AACF,GAhDK,CAAN;AAkDAhB,8DAAM,CAACsB,qEAAY,CAACpB,SAAd,EAAyB,MAAzB,EAAiC,UAAUC,CAAV,EAAa;AAClDtC,KAAC,CAACqB,QAAF,CAAWqC,KAAX;AACD,GAFK,CAAN;;AAIA,MAAIC,GAAG,IAAIA,GAAG,CAACC,aAAf,EAA8B;AAC5BzB,gEAAM,CAACwB,GAAG,CAACC,aAAL,EAAoB,SAApB,EAA+B,UAAStB,CAAT,EAAYuB,OAAZ,EAAqBlE,OAArB,EAA8B;AACjE,UAAIA,OAAO,CAACmE,OAAR,CAAgB,SAAhB,CAAJ,EACEpE,gBAAgB,CAACC,OAAD,CAAhB;AACH,KAHK,CAAN;AAID;AACF,CA9ED,E;;;;;;;;;;;ACvFA,8D;;;;;;;;;;;ACAA,+D;;;;;;;;;;;ACAA,8C","file":"forum.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./forum.js\");\n","export * from './src/forum';\n","// ==================================================\n// fancyBox v3.5.7\n//\n// Licensed GPLv3 for open source use\n// or fancyBox Commercial License for commercial use\n//\n// http://fancyapps.com/fancybox/\n// Copyright 2019 fancyApps\n//\n// ==================================================\n(function (window, document, $, undefined) {\r\n \"use strict\";\r\n\r\n window.console = window.console || {\r\n info: function (stuff) {}\r\n };\r\n\r\n // If there's no jQuery, fancyBox can't work\r\n // =========================================\r\n\r\n if (!$) {\r\n return;\r\n }\r\n\r\n // Check if fancyBox is already initialized\r\n // ========================================\r\n\r\n if ($.fn.fancybox) {\r\n console.info(\"fancyBox already initialized\");\r\n\r\n return;\r\n }\r\n\r\n // Private default settings\r\n // ========================\r\n\r\n var defaults = {\r\n // Close existing modals\r\n // Set this to false if you do not need to stack multiple instances\r\n closeExisting: false,\r\n\r\n // Enable infinite gallery navigation\r\n loop: false,\r\n\r\n // Horizontal space between slides\r\n gutter: 50,\r\n\r\n // Enable keyboard navigation\r\n keyboard: true,\r\n\r\n // Should allow caption to overlap the content\r\n preventCaptionOverlap: true,\r\n\r\n // Should display navigation arrows at the screen edges\r\n arrows: true,\r\n\r\n // Should display counter at the top left corner\r\n infobar: true,\r\n\r\n // Should display close button (using `btnTpl.smallBtn` template) over the content\r\n // Can be true, false, \"auto\"\r\n // If \"auto\" - will be automatically enabled for \"html\", \"inline\" or \"ajax\" items\r\n smallBtn: \"auto\",\r\n\r\n // Should display toolbar (buttons at the top)\r\n // Can be true, false, \"auto\"\r\n // If \"auto\" - will be automatically hidden if \"smallBtn\" is enabled\r\n toolbar: \"auto\",\r\n\r\n // What buttons should appear in the top right corner.\r\n // Buttons will be created using templates from `btnTpl` option\r\n // and they will be placed into toolbar (class=\"fancybox-toolbar\"` element)\r\n buttons: [\r\n \"zoom\",\r\n //\"share\",\r\n \"slideShow\",\r\n //\"fullScreen\",\r\n //\"download\",\r\n \"thumbs\",\r\n \"close\"\r\n ],\r\n\r\n // Detect \"idle\" time in seconds\r\n idleTime: 3,\r\n\r\n // Disable right-click and use simple image protection for images\r\n protect: false,\r\n\r\n // Shortcut to make content \"modal\" - disable keyboard navigtion, hide buttons, etc\r\n modal: false,\r\n\r\n image: {\r\n // Wait for images to load before displaying\r\n // true - wait for image to load and then display;\r\n // false - display thumbnail and load the full-sized image over top,\r\n // requires predefined image dimensions (`data-width` and `data-height` attributes)\r\n preload: false\r\n },\r\n\r\n ajax: {\r\n // Object containing settings for ajax request\r\n settings: {\r\n // This helps to indicate that request comes from the modal\r\n // Feel free to change naming\r\n data: {\r\n fancybox: true\r\n }\r\n }\r\n },\r\n\r\n iframe: {\r\n // Iframe template\r\n tpl: '',\r\n\r\n // Preload iframe before displaying it\r\n // This allows to calculate iframe content width and height\r\n // (note: Due to \"Same Origin Policy\", you can't get cross domain data).\r\n preload: true,\r\n\r\n // Custom CSS styling for iframe wrapping element\r\n // You can use this to set custom iframe dimensions\r\n css: {},\r\n\r\n // Iframe tag attributes\r\n attr: {\r\n scrolling: \"auto\"\r\n }\r\n },\r\n\r\n // For HTML5 video only\r\n video: {\r\n tpl: '\",\r\n format: \"\", // custom video format\r\n autoStart: true\r\n },\r\n\r\n // Default content type if cannot be detected automatically\r\n defaultType: \"image\",\r\n\r\n // Open/close animation type\r\n // Possible values:\r\n // false - disable\r\n // \"zoom\" - zoom images from/to thumbnail\r\n // \"fade\"\r\n // \"zoom-in-out\"\r\n //\r\n animationEffect: \"zoom\",\r\n\r\n // Duration in ms for open/close animation\r\n animationDuration: 366,\r\n\r\n // Should image change opacity while zooming\r\n // If opacity is \"auto\", then opacity will be changed if image and thumbnail have different aspect ratios\r\n zoomOpacity: \"auto\",\r\n\r\n // Transition effect between slides\r\n //\r\n // Possible values:\r\n // false - disable\r\n // \"fade'\r\n // \"slide'\r\n // \"circular'\r\n // \"tube'\r\n // \"zoom-in-out'\r\n // \"rotate'\r\n //\r\n transitionEffect: \"fade\",\r\n\r\n // Duration in ms for transition animation\r\n transitionDuration: 366,\r\n\r\n // Custom CSS class for slide element\r\n slideClass: \"\",\r\n\r\n // Custom CSS class for layout\r\n baseClass: \"\",\r\n\r\n // Base template for layout\r\n baseTpl: '
' +\r\n '
' +\r\n '
' +\r\n '
 / 
' +\r\n '
{{buttons}}
' +\r\n '
{{arrows}}
' +\r\n '
' +\r\n '
' +\r\n \"
\" +\r\n \"
\",\r\n\r\n // Loading indicator template\r\n spinnerTpl: '
',\r\n\r\n // Error message template\r\n errorTpl: '

{{ERROR}}

',\r\n\r\n btnTpl: {\r\n download: '' +\r\n '' +\r\n \"\",\r\n\r\n zoom: '\",\r\n\r\n close: '\",\r\n\r\n // Arrows\r\n arrowLeft: '\",\r\n\r\n arrowRight: '\",\r\n\r\n // This small close button will be appended to your html/inline/ajax content by default,\r\n // if \"smallBtn\" option is not set to false\r\n smallBtn: '\"\r\n },\r\n\r\n // Container is injected into this element\r\n parentEl: \"body\",\r\n\r\n // Hide browser vertical scrollbars; use at your own risk\r\n hideScrollbar: true,\r\n\r\n // Focus handling\r\n // ==============\r\n\r\n // Try to focus on the first focusable element after opening\r\n autoFocus: true,\r\n\r\n // Put focus back to active element after closing\r\n backFocus: true,\r\n\r\n // Do not let user to focus on element outside modal content\r\n trapFocus: true,\r\n\r\n // Module specific options\r\n // =======================\r\n\r\n fullScreen: {\r\n autoStart: false\r\n },\r\n\r\n // Set `touch: false` to disable panning/swiping\r\n touch: {\r\n vertical: true, // Allow to drag content vertically\r\n momentum: true // Continue movement after releasing mouse/touch when panning\r\n },\r\n\r\n // Hash value when initializing manually,\r\n // set `false` to disable hash change\r\n hash: null,\r\n\r\n // Customize or add new media types\r\n // Example:\r\n /*\r\n media : {\r\n youtube : {\r\n params : {\r\n autoplay : 0\r\n }\r\n }\r\n }\r\n */\r\n media: {},\r\n\r\n slideShow: {\r\n autoStart: false,\r\n speed: 3000\r\n },\r\n\r\n thumbs: {\r\n autoStart: false, // Display thumbnails on opening\r\n hideOnClose: true, // Hide thumbnail grid when closing animation starts\r\n parentEl: \".fancybox-container\", // Container is injected into this element\r\n axis: \"y\" // Vertical (y) or horizontal (x) scrolling\r\n },\r\n\r\n // Use mousewheel to navigate gallery\r\n // If 'auto' - enabled for images only\r\n wheel: \"auto\",\r\n\r\n // Callbacks\r\n //==========\r\n\r\n // See Documentation/API/Events for more information\r\n // Example:\r\n /*\r\n afterShow: function( instance, current ) {\r\n console.info( 'Clicked element:' );\r\n console.info( current.opts.$orig );\r\n }\r\n */\r\n\r\n onInit: $.noop, // When instance has been initialized\r\n\r\n beforeLoad: $.noop, // Before the content of a slide is being loaded\r\n afterLoad: $.noop, // When the content of a slide is done loading\r\n\r\n beforeShow: $.noop, // Before open animation starts\r\n afterShow: $.noop, // When content is done loading and animating\r\n\r\n beforeClose: $.noop, // Before the instance attempts to close. Return false to cancel the close.\r\n afterClose: $.noop, // After instance has been closed\r\n\r\n onActivate: $.noop, // When instance is brought to front\r\n onDeactivate: $.noop, // When other instance has been activated\r\n\r\n // Interaction\r\n // ===========\r\n\r\n // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,\r\n // each option can be string or method that returns value.\r\n //\r\n // Possible values:\r\n // \"close\" - close instance\r\n // \"next\" - move to next gallery item\r\n // \"nextOrClose\" - move to next gallery item or close if gallery has only one item\r\n // \"toggleControls\" - show/hide controls\r\n // \"zoom\" - zoom image (if loaded)\r\n // false - do nothing\r\n\r\n // Clicked on the content\r\n clickContent: function (current, event) {\r\n return current.type === \"image\" ? \"zoom\" : false;\r\n },\r\n\r\n // Clicked on the slide\r\n clickSlide: \"close\",\r\n\r\n // Clicked on the background (backdrop) element;\r\n // if you have not changed the layout, then most likely you need to use `clickSlide` option\r\n clickOutside: \"close\",\r\n\r\n // Same as previous two, but for double click\r\n dblclickContent: false,\r\n dblclickSlide: false,\r\n dblclickOutside: false,\r\n\r\n // Custom options when mobile device is detected\r\n // =============================================\r\n\r\n mobile: {\r\n preventCaptionOverlap: false,\r\n idleTime: false,\r\n clickContent: function (current, event) {\r\n return current.type === \"image\" ? \"toggleControls\" : false;\r\n },\r\n clickSlide: function (current, event) {\r\n return current.type === \"image\" ? \"toggleControls\" : \"close\";\r\n },\r\n dblclickContent: function (current, event) {\r\n return current.type === \"image\" ? \"zoom\" : false;\r\n },\r\n dblclickSlide: function (current, event) {\r\n return current.type === \"image\" ? \"zoom\" : false;\r\n }\r\n },\r\n\r\n // Internationalization\r\n // ====================\r\n\r\n lang: \"en\",\r\n i18n: {\r\n en: {\r\n CLOSE: \"Close\",\r\n NEXT: \"Next\",\r\n PREV: \"Previous\",\r\n ERROR: \"The requested content cannot be loaded.
Please try again later.\",\r\n PLAY_START: \"Start slideshow\",\r\n PLAY_STOP: \"Pause slideshow\",\r\n FULL_SCREEN: \"Full screen\",\r\n THUMBS: \"Thumbnails\",\r\n DOWNLOAD: \"Download\",\r\n SHARE: \"Share\",\r\n ZOOM: \"Zoom\"\r\n },\r\n de: {\r\n CLOSE: \"Schließen\",\r\n NEXT: \"Weiter\",\r\n PREV: \"Zurück\",\r\n ERROR: \"Die angeforderten Daten konnten nicht geladen werden.
Bitte versuchen Sie es später nochmal.\",\r\n PLAY_START: \"Diaschau starten\",\r\n PLAY_STOP: \"Diaschau beenden\",\r\n FULL_SCREEN: \"Vollbild\",\r\n THUMBS: \"Vorschaubilder\",\r\n DOWNLOAD: \"Herunterladen\",\r\n SHARE: \"Teilen\",\r\n ZOOM: \"Vergrößern\"\r\n }\r\n }\r\n };\r\n\r\n // Few useful variables and methods\r\n // ================================\r\n\r\n var $W = $(window);\r\n var $D = $(document);\r\n\r\n var called = 0;\r\n\r\n // Check if an object is a jQuery object and not a native JavaScript object\r\n // ========================================================================\r\n var isQuery = function (obj) {\r\n return obj && obj.hasOwnProperty && obj instanceof $;\r\n };\r\n\r\n // Handle multiple browsers for \"requestAnimationFrame\" and \"cancelAnimationFrame\"\r\n // ===============================================================================\r\n var requestAFrame = (function () {\r\n return (\r\n window.requestAnimationFrame ||\r\n window.webkitRequestAnimationFrame ||\r\n window.mozRequestAnimationFrame ||\r\n window.oRequestAnimationFrame ||\r\n // if all else fails, use setTimeout\r\n function (callback) {\r\n return window.setTimeout(callback, 1000 / 60);\r\n }\r\n );\r\n })();\r\n\r\n var cancelAFrame = (function () {\r\n return (\r\n window.cancelAnimationFrame ||\r\n window.webkitCancelAnimationFrame ||\r\n window.mozCancelAnimationFrame ||\r\n window.oCancelAnimationFrame ||\r\n function (id) {\r\n window.clearTimeout(id);\r\n }\r\n );\r\n })();\r\n\r\n // Detect the supported transition-end event property name\r\n // =======================================================\r\n var transitionEnd = (function () {\r\n var el = document.createElement(\"fakeelement\"),\r\n t;\r\n\r\n var transitions = {\r\n transition: \"transitionend\",\r\n OTransition: \"oTransitionEnd\",\r\n MozTransition: \"transitionend\",\r\n WebkitTransition: \"webkitTransitionEnd\"\r\n };\r\n\r\n for (t in transitions) {\r\n if (el.style[t] !== undefined) {\r\n return transitions[t];\r\n }\r\n }\r\n\r\n return \"transitionend\";\r\n })();\r\n\r\n // Force redraw on an element.\r\n // This helps in cases where the browser doesn't redraw an updated element properly\r\n // ================================================================================\r\n var forceRedraw = function ($el) {\r\n return $el && $el.length && $el[0].offsetHeight;\r\n };\r\n\r\n // Exclude array (`buttons`) options from deep merging\r\n // ===================================================\r\n var mergeOpts = function (opts1, opts2) {\r\n var rez = $.extend(true, {}, opts1, opts2);\r\n\r\n $.each(opts2, function (key, value) {\r\n if ($.isArray(value)) {\r\n rez[key] = value;\r\n }\r\n });\r\n\r\n return rez;\r\n };\r\n\r\n // How much of an element is visible in viewport\r\n // =============================================\r\n\r\n var inViewport = function (elem) {\r\n var elemCenter, rez;\r\n\r\n if (!elem || elem.ownerDocument !== document) {\r\n return false;\r\n }\r\n\r\n $(\".fancybox-container\").css(\"pointer-events\", \"none\");\r\n\r\n elemCenter = {\r\n x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,\r\n y: elem.getBoundingClientRect().top + elem.offsetHeight / 2\r\n };\r\n\r\n rez = document.elementFromPoint(elemCenter.x, elemCenter.y) === elem;\r\n\r\n $(\".fancybox-container\").css(\"pointer-events\", \"\");\r\n\r\n return rez;\r\n };\r\n\r\n // Class definition\r\n // ================\r\n\r\n var FancyBox = function (content, opts, index) {\r\n var self = this;\r\n\r\n self.opts = mergeOpts({\r\n index: index\r\n }, $.fancybox.defaults);\r\n\r\n if ($.isPlainObject(opts)) {\r\n self.opts = mergeOpts(self.opts, opts);\r\n }\r\n\r\n if ($.fancybox.isMobile) {\r\n self.opts = mergeOpts(self.opts, self.opts.mobile);\r\n }\r\n\r\n self.id = self.opts.id || ++called;\r\n\r\n self.currIndex = parseInt(self.opts.index, 10) || 0;\r\n self.prevIndex = null;\r\n\r\n self.prevPos = null;\r\n self.currPos = 0;\r\n\r\n self.firstRun = true;\r\n\r\n // All group items\r\n self.group = [];\r\n\r\n // Existing slides (for current, next and previous gallery items)\r\n self.slides = {};\r\n\r\n // Create group elements\r\n self.addContent(content);\r\n\r\n if (!self.group.length) {\r\n return;\r\n }\r\n\r\n self.init();\r\n };\r\n\r\n $.extend(FancyBox.prototype, {\r\n // Create DOM structure\r\n // ====================\r\n\r\n init: function () {\r\n var self = this,\r\n firstItem = self.group[self.currIndex],\r\n firstItemOpts = firstItem.opts,\r\n $container,\r\n buttonStr;\r\n\r\n if (firstItemOpts.closeExisting) {\r\n $.fancybox.close(true);\r\n }\r\n\r\n // Hide scrollbars\r\n // ===============\r\n\r\n $(\"body\").addClass(\"fancybox-active\");\r\n\r\n if (\r\n !$.fancybox.getInstance() &&\r\n firstItemOpts.hideScrollbar !== false &&\r\n !$.fancybox.isMobile &&\r\n document.body.scrollHeight > window.innerHeight\r\n ) {\r\n $(\"head\").append(\r\n '\"\r\n );\r\n\r\n $(\"body\").addClass(\"compensate-for-scrollbar\");\r\n }\r\n\r\n // Build html markup and set references\r\n // ====================================\r\n\r\n // Build html code for buttons and insert into main template\r\n buttonStr = \"\";\r\n\r\n $.each(firstItemOpts.buttons, function (index, value) {\r\n buttonStr += firstItemOpts.btnTpl[value] || \"\";\r\n });\r\n\r\n // Create markup from base template, it will be initially hidden to\r\n // avoid unnecessary work like painting while initializing is not complete\r\n $container = $(\r\n self.translate(\r\n self,\r\n firstItemOpts.baseTpl\r\n .replace(\"{{buttons}}\", buttonStr)\r\n .replace(\"{{arrows}}\", firstItemOpts.btnTpl.arrowLeft + firstItemOpts.btnTpl.arrowRight)\r\n )\r\n )\r\n .attr(\"id\", \"fancybox-container-\" + self.id)\r\n .addClass(firstItemOpts.baseClass)\r\n .data(\"FancyBox\", self)\r\n .appendTo(firstItemOpts.parentEl);\r\n\r\n // Create object holding references to jQuery wrapped nodes\r\n self.$refs = {\r\n container: $container\r\n };\r\n\r\n [\"bg\", \"inner\", \"infobar\", \"toolbar\", \"stage\", \"caption\", \"navigation\"].forEach(function (item) {\r\n self.$refs[item] = $container.find(\".fancybox-\" + item);\r\n });\r\n\r\n self.trigger(\"onInit\");\r\n\r\n // Enable events, deactive previous instances\r\n self.activate();\r\n\r\n // Build slides, load and reveal content\r\n self.jumpTo(self.currIndex);\r\n },\r\n\r\n // Simple i18n support - replaces object keys found in template\r\n // with corresponding values\r\n // ============================================================\r\n\r\n translate: function (obj, str) {\r\n var arr = obj.opts.i18n[obj.opts.lang] || obj.opts.i18n.en;\r\n\r\n return str.replace(/\\{\\{(\\w+)\\}\\}/g, function (match, n) {\r\n return arr[n] === undefined ? match : arr[n];\r\n });\r\n },\r\n\r\n // Populate current group with fresh content\r\n // Check if each object has valid type and content\r\n // ===============================================\r\n\r\n addContent: function (content) {\r\n var self = this,\r\n items = $.makeArray(content),\r\n thumbs;\r\n\r\n $.each(items, function (i, item) {\r\n var obj = {},\r\n opts = {},\r\n $item,\r\n type,\r\n found,\r\n src,\r\n srcParts;\r\n\r\n // Step 1 - Make sure we have an object\r\n // ====================================\r\n\r\n if ($.isPlainObject(item)) {\r\n // We probably have manual usage here, something like\r\n // $.fancybox.open( [ { src : \"image.jpg\", type : \"image\" } ] )\r\n\r\n obj = item;\r\n opts = item.opts || item;\r\n } else if ($.type(item) === \"object\" && $(item).length) {\r\n // Here we probably have jQuery collection returned by some selector\r\n $item = $(item);\r\n\r\n // Support attributes like `data-options='{\"touch\" : false}'` and `data-touch='false'`\r\n opts = $item.data() || {};\r\n opts = $.extend(true, {}, opts, opts.options);\r\n\r\n // Here we store clicked element\r\n opts.$orig = $item;\r\n\r\n obj.src = self.opts.src || opts.src || $item.attr(\"href\");\r\n\r\n // Assume that simple syntax is used, for example:\r\n // `$.fancybox.open( $(\"#test\"), {} );`\r\n if (!obj.type && !obj.src) {\r\n obj.type = \"inline\";\r\n obj.src = item;\r\n }\r\n } else {\r\n // Assume we have a simple html code, for example:\r\n // $.fancybox.open( '

Hi!

' );\r\n obj = {\r\n type: \"html\",\r\n src: item + \"\"\r\n };\r\n }\r\n\r\n // Each gallery object has full collection of options\r\n obj.opts = $.extend(true, {}, self.opts, opts);\r\n\r\n // Do not merge buttons array\r\n if ($.isArray(opts.buttons)) {\r\n obj.opts.buttons = opts.buttons;\r\n }\r\n\r\n if ($.fancybox.isMobile && obj.opts.mobile) {\r\n obj.opts = mergeOpts(obj.opts, obj.opts.mobile);\r\n }\r\n\r\n // Step 2 - Make sure we have content type, if not - try to guess\r\n // ==============================================================\r\n\r\n type = obj.type || obj.opts.type;\r\n src = obj.src || \"\";\r\n\r\n if (!type && src) {\r\n if ((found = src.match(/\\.(mp4|mov|ogv|webm)((\\?|#).*)?$/i))) {\r\n type = \"video\";\r\n\r\n if (!obj.opts.video.format) {\r\n obj.opts.video.format = \"video/\" + (found[1] === \"ogv\" ? \"ogg\" : found[1]);\r\n }\r\n } else if (src.match(/(^data:image\\/[a-z0-9+\\/=]*,)|(\\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\\?|#).*)?$)/i)) {\r\n type = \"image\";\r\n } else if (src.match(/\\.(pdf)((\\?|#).*)?$/i)) {\r\n type = \"iframe\";\r\n obj = $.extend(true, obj, {\r\n contentType: \"pdf\",\r\n opts: {\r\n iframe: {\r\n preload: false\r\n }\r\n }\r\n });\r\n } else if (src.charAt(0) === \"#\") {\r\n type = \"inline\";\r\n }\r\n }\r\n\r\n if (type) {\r\n obj.type = type;\r\n } else {\r\n self.trigger(\"objectNeedsType\", obj);\r\n }\r\n\r\n if (!obj.contentType) {\r\n obj.contentType = $.inArray(obj.type, [\"html\", \"inline\", \"ajax\"]) > -1 ? \"html\" : obj.type;\r\n }\r\n\r\n // Step 3 - Some adjustments\r\n // =========================\r\n\r\n obj.index = self.group.length;\r\n\r\n if (obj.opts.smallBtn == \"auto\") {\r\n obj.opts.smallBtn = $.inArray(obj.type, [\"html\", \"inline\", \"ajax\"]) > -1;\r\n }\r\n\r\n if (obj.opts.toolbar === \"auto\") {\r\n obj.opts.toolbar = !obj.opts.smallBtn;\r\n }\r\n\r\n // Find thumbnail image, check if exists and if is in the viewport\r\n obj.$thumb = obj.opts.$thumb || null;\r\n\r\n if (obj.opts.$trigger && obj.index === self.opts.index) {\r\n obj.$thumb = obj.opts.$trigger.find(\"img:first\");\r\n\r\n if (obj.$thumb.length) {\r\n obj.opts.$orig = obj.opts.$trigger;\r\n }\r\n }\r\n\r\n if (!(obj.$thumb && obj.$thumb.length) && obj.opts.$orig) {\r\n obj.$thumb = obj.opts.$orig.find(\"img:first\");\r\n }\r\n\r\n if (obj.$thumb && !obj.$thumb.length) {\r\n obj.$thumb = null;\r\n }\r\n\r\n obj.thumb = obj.opts.thumb || (obj.$thumb ? obj.$thumb[0].src : null);\r\n\r\n // \"caption\" is a \"special\" option, it can be used to customize caption per gallery item\r\n if ($.type(obj.opts.caption) === \"function\") {\r\n obj.opts.caption = obj.opts.caption.apply(item, [self, obj]);\r\n }\r\n\r\n if ($.type(self.opts.caption) === \"function\") {\r\n obj.opts.caption = self.opts.caption.apply(item, [self, obj]);\r\n }\r\n\r\n // Make sure we have caption as a string or jQuery object\r\n if (!(obj.opts.caption instanceof $)) {\r\n obj.opts.caption = obj.opts.caption === undefined ? \"\" : obj.opts.caption + \"\";\r\n }\r\n\r\n // Check if url contains \"filter\" used to filter the content\r\n // Example: \"ajax.html #something\"\r\n if (obj.type === \"ajax\") {\r\n srcParts = src.split(/\\s+/, 2);\r\n\r\n if (srcParts.length > 1) {\r\n obj.src = srcParts.shift();\r\n\r\n obj.opts.filter = srcParts.shift();\r\n }\r\n }\r\n\r\n // Hide all buttons and disable interactivity for modal items\r\n if (obj.opts.modal) {\r\n obj.opts = $.extend(true, obj.opts, {\r\n trapFocus: true,\r\n // Remove buttons\r\n infobar: 0,\r\n toolbar: 0,\r\n\r\n smallBtn: 0,\r\n\r\n // Disable keyboard navigation\r\n keyboard: 0,\r\n\r\n // Disable some modules\r\n slideShow: 0,\r\n fullScreen: 0,\r\n thumbs: 0,\r\n touch: 0,\r\n\r\n // Disable click event handlers\r\n clickContent: false,\r\n clickSlide: false,\r\n clickOutside: false,\r\n dblclickContent: false,\r\n dblclickSlide: false,\r\n dblclickOutside: false\r\n });\r\n }\r\n\r\n // Step 4 - Add processed object to group\r\n // ======================================\r\n\r\n self.group.push(obj);\r\n });\r\n\r\n // Update controls if gallery is already opened\r\n if (Object.keys(self.slides).length) {\r\n self.updateControls();\r\n\r\n // Update thumbnails, if needed\r\n thumbs = self.Thumbs;\r\n\r\n if (thumbs && thumbs.isActive) {\r\n thumbs.create();\r\n\r\n thumbs.focus();\r\n }\r\n }\r\n },\r\n\r\n // Attach an event handler functions for:\r\n // - navigation buttons\r\n // - browser scrolling, resizing;\r\n // - focusing\r\n // - keyboard\r\n // - detecting inactivity\r\n // ======================================\r\n\r\n addEvents: function () {\r\n var self = this;\r\n\r\n self.removeEvents();\r\n\r\n // Make navigation elements clickable\r\n // ==================================\r\n\r\n self.$refs.container\r\n .on(\"click.fb-close\", \"[data-fancybox-close]\", function (e) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n\r\n self.close(e);\r\n })\r\n .on(\"touchstart.fb-prev click.fb-prev\", \"[data-fancybox-prev]\", function (e) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n\r\n self.previous();\r\n })\r\n .on(\"touchstart.fb-next click.fb-next\", \"[data-fancybox-next]\", function (e) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n\r\n self.next();\r\n })\r\n .on(\"click.fb\", \"[data-fancybox-zoom]\", function (e) {\r\n // Click handler for zoom button\r\n self[self.isScaledDown() ? \"scaleToActual\" : \"scaleToFit\"]();\r\n });\r\n\r\n // Handle page scrolling and browser resizing\r\n // ==========================================\r\n\r\n $W.on(\"orientationchange.fb resize.fb\", function (e) {\r\n if (e && e.originalEvent && e.originalEvent.type === \"resize\") {\r\n if (self.requestId) {\r\n cancelAFrame(self.requestId);\r\n }\r\n\r\n self.requestId = requestAFrame(function () {\r\n self.update(e);\r\n });\r\n } else {\r\n if (self.current && self.current.type === \"iframe\") {\r\n self.$refs.stage.hide();\r\n }\r\n\r\n setTimeout(\r\n function () {\r\n self.$refs.stage.show();\r\n\r\n self.update(e);\r\n },\r\n $.fancybox.isMobile ? 600 : 250\r\n );\r\n }\r\n });\r\n\r\n $D.on(\"keydown.fb\", function (e) {\r\n var instance = $.fancybox ? $.fancybox.getInstance() : null,\r\n current = instance.current,\r\n keycode = e.keyCode || e.which;\r\n\r\n // Trap keyboard focus inside of the modal\r\n // =======================================\r\n\r\n if (keycode == 9) {\r\n if (current.opts.trapFocus) {\r\n self.focus(e);\r\n }\r\n\r\n return;\r\n }\r\n\r\n // Enable keyboard navigation\r\n // ==========================\r\n\r\n if (!current.opts.keyboard || e.ctrlKey || e.altKey || e.shiftKey || $(e.target).is(\"input,textarea,video,audio,select\")) {\r\n return;\r\n }\r\n\r\n // Backspace and Esc keys\r\n if (keycode === 8 || keycode === 27) {\r\n e.preventDefault();\r\n\r\n self.close(e);\r\n\r\n return;\r\n }\r\n\r\n // Left arrow and Up arrow\r\n if (keycode === 37 || keycode === 38) {\r\n e.preventDefault();\r\n\r\n self.previous();\r\n\r\n return;\r\n }\r\n\r\n // Righ arrow and Down arrow\r\n if (keycode === 39 || keycode === 40) {\r\n e.preventDefault();\r\n\r\n self.next();\r\n\r\n return;\r\n }\r\n\r\n self.trigger(\"afterKeydown\", e, keycode);\r\n });\r\n\r\n // Hide controls after some inactivity period\r\n if (self.group[self.currIndex].opts.idleTime) {\r\n self.idleSecondsCounter = 0;\r\n\r\n $D.on(\r\n \"mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle\",\r\n function (e) {\r\n self.idleSecondsCounter = 0;\r\n\r\n if (self.isIdle) {\r\n self.showControls();\r\n }\r\n\r\n self.isIdle = false;\r\n }\r\n );\r\n\r\n self.idleInterval = window.setInterval(function () {\r\n self.idleSecondsCounter++;\r\n\r\n if (self.idleSecondsCounter >= self.group[self.currIndex].opts.idleTime && !self.isDragging) {\r\n self.isIdle = true;\r\n self.idleSecondsCounter = 0;\r\n\r\n self.hideControls();\r\n }\r\n }, 1000);\r\n }\r\n },\r\n\r\n // Remove events added by the core\r\n // ===============================\r\n\r\n removeEvents: function () {\r\n var self = this;\r\n\r\n $W.off(\"orientationchange.fb resize.fb\");\r\n $D.off(\"keydown.fb .fb-idle\");\r\n\r\n this.$refs.container.off(\".fb-close .fb-prev .fb-next\");\r\n\r\n if (self.idleInterval) {\r\n window.clearInterval(self.idleInterval);\r\n\r\n self.idleInterval = null;\r\n }\r\n },\r\n\r\n // Change to previous gallery item\r\n // ===============================\r\n\r\n previous: function (duration) {\r\n return this.jumpTo(this.currPos - 1, duration);\r\n },\r\n\r\n // Change to next gallery item\r\n // ===========================\r\n\r\n next: function (duration) {\r\n return this.jumpTo(this.currPos + 1, duration);\r\n },\r\n\r\n // Switch to selected gallery item\r\n // ===============================\r\n\r\n jumpTo: function (pos, duration) {\r\n var self = this,\r\n groupLen = self.group.length,\r\n firstRun,\r\n isMoved,\r\n loop,\r\n current,\r\n previous,\r\n slidePos,\r\n stagePos,\r\n prop,\r\n diff;\r\n\r\n if (self.isDragging || self.isClosing || (self.isAnimating && self.firstRun)) {\r\n return;\r\n }\r\n\r\n // Should loop?\r\n pos = parseInt(pos, 10);\r\n loop = self.current ? self.current.opts.loop : self.opts.loop;\r\n\r\n if (!loop && (pos < 0 || pos >= groupLen)) {\r\n return false;\r\n }\r\n\r\n // Check if opening for the first time; this helps to speed things up\r\n firstRun = self.firstRun = !Object.keys(self.slides).length;\r\n\r\n // Create slides\r\n previous = self.current;\r\n\r\n self.prevIndex = self.currIndex;\r\n self.prevPos = self.currPos;\r\n\r\n current = self.createSlide(pos);\r\n\r\n if (groupLen > 1) {\r\n if (loop || current.index < groupLen - 1) {\r\n self.createSlide(pos + 1);\r\n }\r\n\r\n if (loop || current.index > 0) {\r\n self.createSlide(pos - 1);\r\n }\r\n }\r\n\r\n self.current = current;\r\n self.currIndex = current.index;\r\n self.currPos = current.pos;\r\n\r\n self.trigger(\"beforeShow\", firstRun);\r\n\r\n self.updateControls();\r\n\r\n // Validate duration length\r\n current.forcedDuration = undefined;\r\n\r\n if ($.isNumeric(duration)) {\r\n current.forcedDuration = duration;\r\n } else {\r\n duration = current.opts[firstRun ? \"animationDuration\" : \"transitionDuration\"];\r\n }\r\n\r\n duration = parseInt(duration, 10);\r\n\r\n // Check if user has swiped the slides or if still animating\r\n isMoved = self.isMoved(current);\r\n\r\n // Make sure current slide is visible\r\n current.$slide.addClass(\"fancybox-slide--current\");\r\n\r\n // Fresh start - reveal container, current slide and start loading content\r\n if (firstRun) {\r\n if (current.opts.animationEffect && duration) {\r\n self.$refs.container.css(\"transition-duration\", duration + \"ms\");\r\n }\r\n\r\n self.$refs.container.addClass(\"fancybox-is-open\").trigger(\"focus\");\r\n\r\n // Attempt to load content into slide\r\n // This will later call `afterLoad` -> `revealContent`\r\n self.loadSlide(current);\r\n\r\n self.preload(\"image\");\r\n\r\n return;\r\n }\r\n\r\n // Get actual slide/stage positions (before cleaning up)\r\n slidePos = $.fancybox.getTranslate(previous.$slide);\r\n stagePos = $.fancybox.getTranslate(self.$refs.stage);\r\n\r\n // Clean up all slides\r\n $.each(self.slides, function (index, slide) {\r\n $.fancybox.stop(slide.$slide, true);\r\n });\r\n\r\n if (previous.pos !== current.pos) {\r\n previous.isComplete = false;\r\n }\r\n\r\n previous.$slide.removeClass(\"fancybox-slide--complete fancybox-slide--current\");\r\n\r\n // If slides are out of place, then animate them to correct position\r\n if (isMoved) {\r\n // Calculate horizontal swipe distance\r\n diff = slidePos.left - (previous.pos * slidePos.width + previous.pos * previous.opts.gutter);\r\n\r\n $.each(self.slides, function (index, slide) {\r\n slide.$slide.removeClass(\"fancybox-animated\").removeClass(function (index, className) {\r\n return (className.match(/(^|\\s)fancybox-fx-\\S+/g) || []).join(\" \");\r\n });\r\n\r\n // Make sure that each slide is in equal distance\r\n // This is mostly needed for freshly added slides, because they are not yet positioned\r\n var leftPos = slide.pos * slidePos.width + slide.pos * slide.opts.gutter;\r\n\r\n $.fancybox.setTranslate(slide.$slide, {\r\n top: 0,\r\n left: leftPos - stagePos.left + diff\r\n });\r\n\r\n if (slide.pos !== current.pos) {\r\n slide.$slide.addClass(\"fancybox-slide--\" + (slide.pos > current.pos ? \"next\" : \"previous\"));\r\n }\r\n\r\n // Redraw to make sure that transition will start\r\n forceRedraw(slide.$slide);\r\n\r\n // Animate the slide\r\n $.fancybox.animate(\r\n slide.$slide, {\r\n top: 0,\r\n left: (slide.pos - current.pos) * slidePos.width + (slide.pos - current.pos) * slide.opts.gutter\r\n },\r\n duration,\r\n function () {\r\n slide.$slide\r\n .css({\r\n transform: \"\",\r\n opacity: \"\"\r\n })\r\n .removeClass(\"fancybox-slide--next fancybox-slide--previous\");\r\n\r\n if (slide.pos === self.currPos) {\r\n self.complete();\r\n }\r\n }\r\n );\r\n });\r\n } else if (duration && current.opts.transitionEffect) {\r\n // Set transition effect for previously active slide\r\n prop = \"fancybox-animated fancybox-fx-\" + current.opts.transitionEffect;\r\n\r\n previous.$slide.addClass(\"fancybox-slide--\" + (previous.pos > current.pos ? \"next\" : \"previous\"));\r\n\r\n $.fancybox.animate(\r\n previous.$slide,\r\n prop,\r\n duration,\r\n function () {\r\n previous.$slide.removeClass(prop).removeClass(\"fancybox-slide--next fancybox-slide--previous\");\r\n },\r\n false\r\n );\r\n }\r\n\r\n if (current.isLoaded) {\r\n self.revealContent(current);\r\n } else {\r\n self.loadSlide(current);\r\n }\r\n\r\n self.preload(\"image\");\r\n },\r\n\r\n // Create new \"slide\" element\r\n // These are gallery items that are actually added to DOM\r\n // =======================================================\r\n\r\n createSlide: function (pos) {\r\n var self = this,\r\n $slide,\r\n index;\r\n\r\n index = pos % self.group.length;\r\n index = index < 0 ? self.group.length + index : index;\r\n\r\n if (!self.slides[pos] && self.group[index]) {\r\n $slide = $('
').appendTo(self.$refs.stage);\r\n\r\n self.slides[pos] = $.extend(true, {}, self.group[index], {\r\n pos: pos,\r\n $slide: $slide,\r\n isLoaded: false\r\n });\r\n\r\n self.updateSlide(self.slides[pos]);\r\n }\r\n\r\n return self.slides[pos];\r\n },\r\n\r\n // Scale image to the actual size of the image;\r\n // x and y values should be relative to the slide\r\n // ==============================================\r\n\r\n scaleToActual: function (x, y, duration) {\r\n var self = this,\r\n current = self.current,\r\n $content = current.$content,\r\n canvasWidth = $.fancybox.getTranslate(current.$slide).width,\r\n canvasHeight = $.fancybox.getTranslate(current.$slide).height,\r\n newImgWidth = current.width,\r\n newImgHeight = current.height,\r\n imgPos,\r\n posX,\r\n posY,\r\n scaleX,\r\n scaleY;\r\n\r\n if (self.isAnimating || self.isMoved() || !$content || !(current.type == \"image\" && current.isLoaded && !current.hasError)) {\r\n return;\r\n }\r\n\r\n self.isAnimating = true;\r\n\r\n $.fancybox.stop($content);\r\n\r\n x = x === undefined ? canvasWidth * 0.5 : x;\r\n y = y === undefined ? canvasHeight * 0.5 : y;\r\n\r\n imgPos = $.fancybox.getTranslate($content);\r\n\r\n imgPos.top -= $.fancybox.getTranslate(current.$slide).top;\r\n imgPos.left -= $.fancybox.getTranslate(current.$slide).left;\r\n\r\n scaleX = newImgWidth / imgPos.width;\r\n scaleY = newImgHeight / imgPos.height;\r\n\r\n // Get center position for original image\r\n posX = canvasWidth * 0.5 - newImgWidth * 0.5;\r\n posY = canvasHeight * 0.5 - newImgHeight * 0.5;\r\n\r\n // Make sure image does not move away from edges\r\n if (newImgWidth > canvasWidth) {\r\n posX = imgPos.left * scaleX - (x * scaleX - x);\r\n\r\n if (posX > 0) {\r\n posX = 0;\r\n }\r\n\r\n if (posX < canvasWidth - newImgWidth) {\r\n posX = canvasWidth - newImgWidth;\r\n }\r\n }\r\n\r\n if (newImgHeight > canvasHeight) {\r\n posY = imgPos.top * scaleY - (y * scaleY - y);\r\n\r\n if (posY > 0) {\r\n posY = 0;\r\n }\r\n\r\n if (posY < canvasHeight - newImgHeight) {\r\n posY = canvasHeight - newImgHeight;\r\n }\r\n }\r\n\r\n self.updateCursor(newImgWidth, newImgHeight);\r\n\r\n $.fancybox.animate(\r\n $content, {\r\n top: posY,\r\n left: posX,\r\n scaleX: scaleX,\r\n scaleY: scaleY\r\n },\r\n duration || 366,\r\n function () {\r\n self.isAnimating = false;\r\n }\r\n );\r\n\r\n // Stop slideshow\r\n if (self.SlideShow && self.SlideShow.isActive) {\r\n self.SlideShow.stop();\r\n }\r\n },\r\n\r\n // Scale image to fit inside parent element\r\n // ========================================\r\n\r\n scaleToFit: function (duration) {\r\n var self = this,\r\n current = self.current,\r\n $content = current.$content,\r\n end;\r\n\r\n if (self.isAnimating || self.isMoved() || !$content || !(current.type == \"image\" && current.isLoaded && !current.hasError)) {\r\n return;\r\n }\r\n\r\n self.isAnimating = true;\r\n\r\n $.fancybox.stop($content);\r\n\r\n end = self.getFitPos(current);\r\n\r\n self.updateCursor(end.width, end.height);\r\n\r\n $.fancybox.animate(\r\n $content, {\r\n top: end.top,\r\n left: end.left,\r\n scaleX: end.width / $content.width(),\r\n scaleY: end.height / $content.height()\r\n },\r\n duration || 366,\r\n function () {\r\n self.isAnimating = false;\r\n }\r\n );\r\n },\r\n\r\n // Calculate image size to fit inside viewport\r\n // ===========================================\r\n\r\n getFitPos: function (slide) {\r\n var self = this,\r\n $content = slide.$content,\r\n $slide = slide.$slide,\r\n width = slide.width || slide.opts.width,\r\n height = slide.height || slide.opts.height,\r\n maxWidth,\r\n maxHeight,\r\n minRatio,\r\n aspectRatio,\r\n rez = {};\r\n\r\n if (!slide.isLoaded || !$content || !$content.length) {\r\n return false;\r\n }\r\n\r\n maxWidth = $.fancybox.getTranslate(self.$refs.stage).width;\r\n maxHeight = $.fancybox.getTranslate(self.$refs.stage).height;\r\n\r\n maxWidth -=\r\n parseFloat($slide.css(\"paddingLeft\")) +\r\n parseFloat($slide.css(\"paddingRight\")) +\r\n parseFloat($content.css(\"marginLeft\")) +\r\n parseFloat($content.css(\"marginRight\"));\r\n\r\n maxHeight -=\r\n parseFloat($slide.css(\"paddingTop\")) +\r\n parseFloat($slide.css(\"paddingBottom\")) +\r\n parseFloat($content.css(\"marginTop\")) +\r\n parseFloat($content.css(\"marginBottom\"));\r\n\r\n if (!width || !height) {\r\n width = maxWidth;\r\n height = maxHeight;\r\n }\r\n\r\n minRatio = Math.min(1, maxWidth / width, maxHeight / height);\r\n\r\n width = minRatio * width;\r\n height = minRatio * height;\r\n\r\n // Adjust width/height to precisely fit into container\r\n if (width > maxWidth - 0.5) {\r\n width = maxWidth;\r\n }\r\n\r\n if (height > maxHeight - 0.5) {\r\n height = maxHeight;\r\n }\r\n\r\n if (slide.type === \"image\") {\r\n rez.top = Math.floor((maxHeight - height) * 0.5) + parseFloat($slide.css(\"paddingTop\"));\r\n rez.left = Math.floor((maxWidth - width) * 0.5) + parseFloat($slide.css(\"paddingLeft\"));\r\n } else if (slide.contentType === \"video\") {\r\n // Force aspect ratio for the video\r\n // \"I say the whole world must learn of our peaceful ways… by force!\"\r\n aspectRatio = slide.opts.width && slide.opts.height ? width / height : slide.opts.ratio || 16 / 9;\r\n\r\n if (height > width / aspectRatio) {\r\n height = width / aspectRatio;\r\n } else if (width > height * aspectRatio) {\r\n width = height * aspectRatio;\r\n }\r\n }\r\n\r\n rez.width = width;\r\n rez.height = height;\r\n\r\n return rez;\r\n },\r\n\r\n // Update content size and position for all slides\r\n // ==============================================\r\n\r\n update: function (e) {\r\n var self = this;\r\n\r\n $.each(self.slides, function (key, slide) {\r\n self.updateSlide(slide, e);\r\n });\r\n },\r\n\r\n // Update slide content position and size\r\n // ======================================\r\n\r\n updateSlide: function (slide, e) {\r\n var self = this,\r\n $content = slide && slide.$content,\r\n width = slide.width || slide.opts.width,\r\n height = slide.height || slide.opts.height,\r\n $slide = slide.$slide;\r\n\r\n // First, prevent caption overlap, if needed\r\n self.adjustCaption(slide);\r\n\r\n // Then resize content to fit inside the slide\r\n if ($content && (width || height || slide.contentType === \"video\") && !slide.hasError) {\r\n $.fancybox.stop($content);\r\n\r\n $.fancybox.setTranslate($content, self.getFitPos(slide));\r\n\r\n if (slide.pos === self.currPos) {\r\n self.isAnimating = false;\r\n\r\n self.updateCursor();\r\n }\r\n }\r\n\r\n // Then some adjustments\r\n self.adjustLayout(slide);\r\n\r\n if ($slide.length) {\r\n $slide.trigger(\"refresh\");\r\n\r\n if (slide.pos === self.currPos) {\r\n self.$refs.toolbar\r\n .add(self.$refs.navigation.find(\".fancybox-button--arrow_right\"))\r\n .toggleClass(\"compensate-for-scrollbar\", $slide.get(0).scrollHeight > $slide.get(0).clientHeight);\r\n }\r\n }\r\n\r\n self.trigger(\"onUpdate\", slide, e);\r\n },\r\n\r\n // Horizontally center slide\r\n // =========================\r\n\r\n centerSlide: function (duration) {\r\n var self = this,\r\n current = self.current,\r\n $slide = current.$slide;\r\n\r\n if (self.isClosing || !current) {\r\n return;\r\n }\r\n\r\n $slide.siblings().css({\r\n transform: \"\",\r\n opacity: \"\"\r\n });\r\n\r\n $slide\r\n .parent()\r\n .children()\r\n .removeClass(\"fancybox-slide--previous fancybox-slide--next\");\r\n\r\n $.fancybox.animate(\r\n $slide, {\r\n top: 0,\r\n left: 0,\r\n opacity: 1\r\n },\r\n duration === undefined ? 0 : duration,\r\n function () {\r\n // Clean up\r\n $slide.css({\r\n transform: \"\",\r\n opacity: \"\"\r\n });\r\n\r\n if (!current.isComplete) {\r\n self.complete();\r\n }\r\n },\r\n false\r\n );\r\n },\r\n\r\n // Check if current slide is moved (swiped)\r\n // ========================================\r\n\r\n isMoved: function (slide) {\r\n var current = slide || this.current,\r\n slidePos,\r\n stagePos;\r\n\r\n if (!current) {\r\n return false;\r\n }\r\n\r\n stagePos = $.fancybox.getTranslate(this.$refs.stage);\r\n slidePos = $.fancybox.getTranslate(current.$slide);\r\n\r\n return (\r\n !current.$slide.hasClass(\"fancybox-animated\") &&\r\n (Math.abs(slidePos.top - stagePos.top) > 0.5 || Math.abs(slidePos.left - stagePos.left) > 0.5)\r\n );\r\n },\r\n\r\n // Update cursor style depending if content can be zoomed\r\n // ======================================================\r\n\r\n updateCursor: function (nextWidth, nextHeight) {\r\n var self = this,\r\n current = self.current,\r\n $container = self.$refs.container,\r\n canPan,\r\n isZoomable;\r\n\r\n if (!current || self.isClosing || !self.Guestures) {\r\n return;\r\n }\r\n\r\n $container.removeClass(\"fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-zoomOut fancybox-can-swipe fancybox-can-pan\");\r\n\r\n canPan = self.canPan(nextWidth, nextHeight);\r\n\r\n isZoomable = canPan ? true : self.isZoomable();\r\n\r\n $container.toggleClass(\"fancybox-is-zoomable\", isZoomable);\r\n\r\n $(\"[data-fancybox-zoom]\").prop(\"disabled\", !isZoomable);\r\n\r\n if (canPan) {\r\n $container.addClass(\"fancybox-can-pan\");\r\n } else if (\r\n isZoomable &&\r\n (current.opts.clickContent === \"zoom\" || ($.isFunction(current.opts.clickContent) && current.opts.clickContent(current) == \"zoom\"))\r\n ) {\r\n $container.addClass(\"fancybox-can-zoomIn\");\r\n } else if (current.opts.touch && (current.opts.touch.vertical || self.group.length > 1) && current.contentType !== \"video\") {\r\n $container.addClass(\"fancybox-can-swipe\");\r\n }\r\n },\r\n\r\n // Check if current slide is zoomable\r\n // ==================================\r\n\r\n isZoomable: function () {\r\n var self = this,\r\n current = self.current,\r\n fitPos;\r\n\r\n // Assume that slide is zoomable if:\r\n // - image is still loading\r\n // - actual size of the image is smaller than available area\r\n if (current && !self.isClosing && current.type === \"image\" && !current.hasError) {\r\n if (!current.isLoaded) {\r\n return true;\r\n }\r\n\r\n fitPos = self.getFitPos(current);\r\n\r\n if (fitPos && (current.width > fitPos.width || current.height > fitPos.height)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n },\r\n\r\n // Check if current image dimensions are smaller than actual\r\n // =========================================================\r\n\r\n isScaledDown: function (nextWidth, nextHeight) {\r\n var self = this,\r\n rez = false,\r\n current = self.current,\r\n $content = current.$content;\r\n\r\n if (nextWidth !== undefined && nextHeight !== undefined) {\r\n rez = nextWidth < current.width && nextHeight < current.height;\r\n } else if ($content) {\r\n rez = $.fancybox.getTranslate($content);\r\n rez = rez.width < current.width && rez.height < current.height;\r\n }\r\n\r\n return rez;\r\n },\r\n\r\n // Check if image dimensions exceed parent element\r\n // ===============================================\r\n\r\n canPan: function (nextWidth, nextHeight) {\r\n var self = this,\r\n current = self.current,\r\n pos = null,\r\n rez = false;\r\n\r\n if (current.type === \"image\" && (current.isComplete || (nextWidth && nextHeight)) && !current.hasError) {\r\n rez = self.getFitPos(current);\r\n\r\n if (nextWidth !== undefined && nextHeight !== undefined) {\r\n pos = {\r\n width: nextWidth,\r\n height: nextHeight\r\n };\r\n } else if (current.isComplete) {\r\n pos = $.fancybox.getTranslate(current.$content);\r\n }\r\n\r\n if (pos && rez) {\r\n rez = Math.abs(pos.width - rez.width) > 1.5 || Math.abs(pos.height - rez.height) > 1.5;\r\n }\r\n }\r\n\r\n return rez;\r\n },\r\n\r\n // Load content into the slide\r\n // ===========================\r\n\r\n loadSlide: function (slide) {\r\n var self = this,\r\n type,\r\n $slide,\r\n ajaxLoad;\r\n\r\n if (slide.isLoading || slide.isLoaded) {\r\n return;\r\n }\r\n\r\n slide.isLoading = true;\r\n\r\n if (self.trigger(\"beforeLoad\", slide) === false) {\r\n slide.isLoading = false;\r\n\r\n return false;\r\n }\r\n\r\n type = slide.type;\r\n $slide = slide.$slide;\r\n\r\n $slide\r\n .off(\"refresh\")\r\n .trigger(\"onReset\")\r\n .addClass(slide.opts.slideClass);\r\n\r\n // Create content depending on the type\r\n switch (type) {\r\n case \"image\":\r\n self.setImage(slide);\r\n\r\n break;\r\n\r\n case \"iframe\":\r\n self.setIframe(slide);\r\n\r\n break;\r\n\r\n case \"html\":\r\n self.setContent(slide, slide.src || slide.content);\r\n\r\n break;\r\n\r\n case \"video\":\r\n self.setContent(\r\n slide,\r\n slide.opts.video.tpl\r\n .replace(/\\{\\{src\\}\\}/gi, slide.src)\r\n .replace(\"{{format}}\", slide.opts.videoFormat || slide.opts.video.format || \"\")\r\n .replace(\"{{poster}}\", slide.thumb || \"\")\r\n );\r\n\r\n break;\r\n\r\n case \"inline\":\r\n if ($(slide.src).length) {\r\n self.setContent(slide, $(slide.src));\r\n } else {\r\n self.setError(slide);\r\n }\r\n\r\n break;\r\n\r\n case \"ajax\":\r\n self.showLoading(slide);\r\n\r\n ajaxLoad = $.ajax(\r\n $.extend({}, slide.opts.ajax.settings, {\r\n url: slide.src,\r\n success: function (data, textStatus) {\r\n if (textStatus === \"success\") {\r\n self.setContent(slide, data);\r\n }\r\n },\r\n error: function (jqXHR, textStatus) {\r\n if (jqXHR && textStatus !== \"abort\") {\r\n self.setError(slide);\r\n }\r\n }\r\n })\r\n );\r\n\r\n $slide.one(\"onReset\", function () {\r\n ajaxLoad.abort();\r\n });\r\n\r\n break;\r\n\r\n default:\r\n self.setError(slide);\r\n\r\n break;\r\n }\r\n\r\n return true;\r\n },\r\n\r\n // Use thumbnail image, if possible\r\n // ================================\r\n\r\n setImage: function (slide) {\r\n var self = this,\r\n ghost;\r\n\r\n // Check if need to show loading icon\r\n setTimeout(function () {\r\n var $img = slide.$image;\r\n\r\n if (!self.isClosing && slide.isLoading && (!$img || !$img.length || !$img[0].complete) && !slide.hasError) {\r\n self.showLoading(slide);\r\n }\r\n }, 50);\r\n\r\n //Check if image has srcset\r\n self.checkSrcset(slide);\r\n\r\n // This will be wrapper containing both ghost and actual image\r\n slide.$content = $('
')\r\n .addClass(\"fancybox-is-hidden\")\r\n .appendTo(slide.$slide.addClass(\"fancybox-slide--image\"));\r\n\r\n // If we have a thumbnail, we can display it while actual image is loading\r\n // Users will not stare at black screen and actual image will appear gradually\r\n if (slide.opts.preload !== false && slide.opts.width && slide.opts.height && slide.thumb) {\r\n slide.width = slide.opts.width;\r\n slide.height = slide.opts.height;\r\n\r\n ghost = document.createElement(\"img\");\r\n\r\n ghost.onerror = function () {\r\n $(this).remove();\r\n\r\n slide.$ghost = null;\r\n };\r\n\r\n ghost.onload = function () {\r\n self.afterLoad(slide);\r\n };\r\n\r\n slide.$ghost = $(ghost)\r\n .addClass(\"fancybox-image\")\r\n .appendTo(slide.$content)\r\n .attr(\"src\", slide.thumb);\r\n }\r\n\r\n // Start loading actual image\r\n self.setBigImage(slide);\r\n },\r\n\r\n // Check if image has srcset and get the source\r\n // ============================================\r\n checkSrcset: function (slide) {\r\n var srcset = slide.opts.srcset || slide.opts.image.srcset,\r\n found,\r\n temp,\r\n pxRatio,\r\n windowWidth;\r\n\r\n // If we have \"srcset\", then we need to find first matching \"src\" value.\r\n // This is necessary, because when you set an src attribute, the browser will preload the image\r\n // before any javascript or even CSS is applied.\r\n if (srcset) {\r\n pxRatio = window.devicePixelRatio || 1;\r\n windowWidth = window.innerWidth * pxRatio;\r\n\r\n temp = srcset.split(\",\").map(function (el) {\r\n var ret = {};\r\n\r\n el.trim()\r\n .split(/\\s+/)\r\n .forEach(function (el, i) {\r\n var value = parseInt(el.substring(0, el.length - 1), 10);\r\n\r\n if (i === 0) {\r\n return (ret.url = el);\r\n }\r\n\r\n if (value) {\r\n ret.value = value;\r\n ret.postfix = el[el.length - 1];\r\n }\r\n });\r\n\r\n return ret;\r\n });\r\n\r\n // Sort by value\r\n temp.sort(function (a, b) {\r\n return a.value - b.value;\r\n });\r\n\r\n // Ok, now we have an array of all srcset values\r\n for (var j = 0; j < temp.length; j++) {\r\n var el = temp[j];\r\n\r\n if ((el.postfix === \"w\" && el.value >= windowWidth) || (el.postfix === \"x\" && el.value >= pxRatio)) {\r\n found = el;\r\n break;\r\n }\r\n }\r\n\r\n // If not found, take the last one\r\n if (!found && temp.length) {\r\n found = temp[temp.length - 1];\r\n }\r\n\r\n if (found) {\r\n slide.src = found.url;\r\n\r\n // If we have default width/height values, we can calculate height for matching source\r\n if (slide.width && slide.height && found.postfix == \"w\") {\r\n slide.height = (slide.width / slide.height) * found.value;\r\n slide.width = found.value;\r\n }\r\n\r\n slide.opts.srcset = srcset;\r\n }\r\n }\r\n },\r\n\r\n // Create full-size image\r\n // ======================\r\n\r\n setBigImage: function (slide) {\r\n var self = this,\r\n img = document.createElement(\"img\"),\r\n $img = $(img);\r\n\r\n slide.$image = $img\r\n .one(\"error\", function () {\r\n self.setError(slide);\r\n })\r\n .one(\"load\", function () {\r\n var sizes;\r\n\r\n if (!slide.$ghost) {\r\n self.resolveImageSlideSize(slide, this.naturalWidth, this.naturalHeight);\r\n\r\n self.afterLoad(slide);\r\n }\r\n\r\n if (self.isClosing) {\r\n return;\r\n }\r\n\r\n if (slide.opts.srcset) {\r\n sizes = slide.opts.sizes;\r\n\r\n if (!sizes || sizes === \"auto\") {\r\n sizes =\r\n (slide.width / slide.height > 1 && $W.width() / $W.height() > 1 ? \"100\" : Math.round((slide.width / slide.height) * 100)) +\r\n \"vw\";\r\n }\r\n\r\n $img.attr(\"sizes\", sizes).attr(\"srcset\", slide.opts.srcset);\r\n }\r\n\r\n // Hide temporary image after some delay\r\n if (slide.$ghost) {\r\n setTimeout(function () {\r\n if (slide.$ghost && !self.isClosing) {\r\n slide.$ghost.hide();\r\n }\r\n }, Math.min(300, Math.max(1000, slide.height / 1600)));\r\n }\r\n\r\n self.hideLoading(slide);\r\n })\r\n .addClass(\"fancybox-image\")\r\n .attr(\"src\", slide.src)\r\n .appendTo(slide.$content);\r\n\r\n if ((img.complete || img.readyState == \"complete\") && $img.naturalWidth && $img.naturalHeight) {\r\n $img.trigger(\"load\");\r\n } else if (img.error) {\r\n $img.trigger(\"error\");\r\n }\r\n },\r\n\r\n // Computes the slide size from image size and maxWidth/maxHeight\r\n // ==============================================================\r\n\r\n resolveImageSlideSize: function (slide, imgWidth, imgHeight) {\r\n var maxWidth = parseInt(slide.opts.width, 10),\r\n maxHeight = parseInt(slide.opts.height, 10);\r\n\r\n // Sets the default values from the image\r\n slide.width = imgWidth;\r\n slide.height = imgHeight;\r\n\r\n if (maxWidth > 0) {\r\n slide.width = maxWidth;\r\n slide.height = Math.floor((maxWidth * imgHeight) / imgWidth);\r\n }\r\n\r\n if (maxHeight > 0) {\r\n slide.width = Math.floor((maxHeight * imgWidth) / imgHeight);\r\n slide.height = maxHeight;\r\n }\r\n },\r\n\r\n // Create iframe wrapper, iframe and bindings\r\n // ==========================================\r\n\r\n setIframe: function (slide) {\r\n var self = this,\r\n opts = slide.opts.iframe,\r\n $slide = slide.$slide,\r\n $iframe;\r\n\r\n slide.$content = $('
')\r\n .css(opts.css)\r\n .appendTo($slide);\r\n\r\n $slide.addClass(\"fancybox-slide--\" + slide.contentType);\r\n\r\n slide.$iframe = $iframe = $(opts.tpl.replace(/\\{rnd\\}/g, new Date().getTime()))\r\n .attr(opts.attr)\r\n .appendTo(slide.$content);\r\n\r\n if (opts.preload) {\r\n self.showLoading(slide);\r\n\r\n // Unfortunately, it is not always possible to determine if iframe is successfully loaded\r\n // (due to browser security policy)\r\n\r\n $iframe.on(\"load.fb error.fb\", function (e) {\r\n this.isReady = 1;\r\n\r\n slide.$slide.trigger(\"refresh\");\r\n\r\n self.afterLoad(slide);\r\n });\r\n\r\n // Recalculate iframe content size\r\n // ===============================\r\n\r\n $slide.on(\"refresh.fb\", function () {\r\n var $content = slide.$content,\r\n frameWidth = opts.css.width,\r\n frameHeight = opts.css.height,\r\n $contents,\r\n $body;\r\n\r\n if ($iframe[0].isReady !== 1) {\r\n return;\r\n }\r\n\r\n try {\r\n $contents = $iframe.contents();\r\n $body = $contents.find(\"body\");\r\n } catch (ignore) {}\r\n\r\n // Calculate content dimensions, if it is accessible\r\n if ($body && $body.length && $body.children().length) {\r\n // Avoid scrolling to top (if multiple instances)\r\n $slide.css(\"overflow\", \"visible\");\r\n\r\n $content.css({\r\n width: \"100%\",\r\n \"max-width\": \"100%\",\r\n height: \"9999px\"\r\n });\r\n\r\n if (frameWidth === undefined) {\r\n frameWidth = Math.ceil(Math.max($body[0].clientWidth, $body.outerWidth(true)));\r\n }\r\n\r\n $content.css(\"width\", frameWidth ? frameWidth : \"\").css(\"max-width\", \"\");\r\n\r\n if (frameHeight === undefined) {\r\n frameHeight = Math.ceil(Math.max($body[0].clientHeight, $body.outerHeight(true)));\r\n }\r\n\r\n $content.css(\"height\", frameHeight ? frameHeight : \"\");\r\n\r\n $slide.css(\"overflow\", \"auto\");\r\n }\r\n\r\n $content.removeClass(\"fancybox-is-hidden\");\r\n });\r\n } else {\r\n self.afterLoad(slide);\r\n }\r\n\r\n $iframe.attr(\"src\", slide.src);\r\n\r\n // Remove iframe if closing or changing gallery item\r\n $slide.one(\"onReset\", function () {\r\n // This helps IE not to throw errors when closing\r\n try {\r\n $(this)\r\n .find(\"iframe\")\r\n .hide()\r\n .unbind()\r\n .attr(\"src\", \"//about:blank\");\r\n } catch (ignore) {}\r\n\r\n $(this)\r\n .off(\"refresh.fb\")\r\n .empty();\r\n\r\n slide.isLoaded = false;\r\n slide.isRevealed = false;\r\n });\r\n },\r\n\r\n // Wrap and append content to the slide\r\n // ======================================\r\n\r\n setContent: function (slide, content) {\r\n var self = this;\r\n\r\n if (self.isClosing) {\r\n return;\r\n }\r\n\r\n self.hideLoading(slide);\r\n\r\n if (slide.$content) {\r\n $.fancybox.stop(slide.$content);\r\n }\r\n\r\n slide.$slide.empty();\r\n\r\n // If content is a jQuery object, then it will be moved to the slide.\r\n // The placeholder is created so we will know where to put it back.\r\n if (isQuery(content) && content.parent().length) {\r\n // Make sure content is not already moved to fancyBox\r\n if (content.hasClass(\"fancybox-content\") || content.parent().hasClass(\"fancybox-content\")) {\r\n content.parents(\".fancybox-slide\").trigger(\"onReset\");\r\n }\r\n\r\n // Create temporary element marking original place of the content\r\n slide.$placeholder = $(\"
\")\r\n .hide()\r\n .insertAfter(content);\r\n\r\n // Make sure content is visible\r\n content.css(\"display\", \"inline-block\");\r\n } else if (!slide.hasError) {\r\n // If content is just a plain text, try to convert it to html\r\n if ($.type(content) === \"string\") {\r\n content = $(\"
\")\r\n .append($.trim(content))\r\n .contents();\r\n }\r\n\r\n // If \"filter\" option is provided, then filter content\r\n if (slide.opts.filter) {\r\n content = $(\"
\")\r\n .html(content)\r\n .find(slide.opts.filter);\r\n }\r\n }\r\n\r\n slide.$slide.one(\"onReset\", function () {\r\n // Pause all html5 video/audio\r\n $(this)\r\n .find(\"video,audio\")\r\n .trigger(\"pause\");\r\n\r\n // Put content back\r\n if (slide.$placeholder) {\r\n slide.$placeholder.after(content.removeClass(\"fancybox-content\").hide()).remove();\r\n\r\n slide.$placeholder = null;\r\n }\r\n\r\n // Remove custom close button\r\n if (slide.$smallBtn) {\r\n slide.$smallBtn.remove();\r\n\r\n slide.$smallBtn = null;\r\n }\r\n\r\n // Remove content and mark slide as not loaded\r\n if (!slide.hasError) {\r\n $(this).empty();\r\n\r\n slide.isLoaded = false;\r\n slide.isRevealed = false;\r\n }\r\n });\r\n\r\n $(content).appendTo(slide.$slide);\r\n\r\n if ($(content).is(\"video,audio\")) {\r\n $(content).addClass(\"fancybox-video\");\r\n\r\n $(content).wrap(\"
\");\r\n\r\n slide.contentType = \"video\";\r\n\r\n slide.opts.width = slide.opts.width || $(content).attr(\"width\");\r\n slide.opts.height = slide.opts.height || $(content).attr(\"height\");\r\n }\r\n\r\n slide.$content = slide.$slide\r\n .children()\r\n .filter(\"div,form,main,video,audio,article,.fancybox-content\")\r\n .first();\r\n\r\n slide.$content.siblings().hide();\r\n\r\n // Re-check if there is a valid content\r\n // (in some cases, ajax response can contain various elements or plain text)\r\n if (!slide.$content.length) {\r\n slide.$content = slide.$slide\r\n .wrapInner(\"
\")\r\n .children()\r\n .first();\r\n }\r\n\r\n slide.$content.addClass(\"fancybox-content\");\r\n\r\n slide.$slide.addClass(\"fancybox-slide--\" + slide.contentType);\r\n\r\n self.afterLoad(slide);\r\n },\r\n\r\n // Display error message\r\n // =====================\r\n\r\n setError: function (slide) {\r\n slide.hasError = true;\r\n\r\n slide.$slide\r\n .trigger(\"onReset\")\r\n .removeClass(\"fancybox-slide--\" + slide.contentType)\r\n .addClass(\"fancybox-slide--error\");\r\n\r\n slide.contentType = \"html\";\r\n\r\n this.setContent(slide, this.translate(slide, slide.opts.errorTpl));\r\n\r\n if (slide.pos === this.currPos) {\r\n this.isAnimating = false;\r\n }\r\n },\r\n\r\n // Show loading icon inside the slide\r\n // ==================================\r\n\r\n showLoading: function (slide) {\r\n var self = this;\r\n\r\n slide = slide || self.current;\r\n\r\n if (slide && !slide.$spinner) {\r\n slide.$spinner = $(self.translate(self, self.opts.spinnerTpl))\r\n .appendTo(slide.$slide)\r\n .hide()\r\n .fadeIn(\"fast\");\r\n }\r\n },\r\n\r\n // Remove loading icon from the slide\r\n // ==================================\r\n\r\n hideLoading: function (slide) {\r\n var self = this;\r\n\r\n slide = slide || self.current;\r\n\r\n if (slide && slide.$spinner) {\r\n slide.$spinner.stop().remove();\r\n\r\n delete slide.$spinner;\r\n }\r\n },\r\n\r\n // Adjustments after slide content has been loaded\r\n // ===============================================\r\n\r\n afterLoad: function (slide) {\r\n var self = this;\r\n\r\n if (self.isClosing) {\r\n return;\r\n }\r\n\r\n slide.isLoading = false;\r\n slide.isLoaded = true;\r\n\r\n self.trigger(\"afterLoad\", slide);\r\n\r\n self.hideLoading(slide);\r\n\r\n // Add small close button\r\n if (slide.opts.smallBtn && (!slide.$smallBtn || !slide.$smallBtn.length)) {\r\n slide.$smallBtn = $(self.translate(slide, slide.opts.btnTpl.smallBtn)).appendTo(slide.$content);\r\n }\r\n\r\n // Disable right click\r\n if (slide.opts.protect && slide.$content && !slide.hasError) {\r\n slide.$content.on(\"contextmenu.fb\", function (e) {\r\n if (e.button == 2) {\r\n e.preventDefault();\r\n }\r\n\r\n return true;\r\n });\r\n\r\n // Add fake element on top of the image\r\n // This makes a bit harder for user to select image\r\n if (slide.type === \"image\") {\r\n $('
').appendTo(slide.$content);\r\n }\r\n }\r\n\r\n self.adjustCaption(slide);\r\n\r\n self.adjustLayout(slide);\r\n\r\n if (slide.pos === self.currPos) {\r\n self.updateCursor();\r\n }\r\n\r\n self.revealContent(slide);\r\n },\r\n\r\n // Prevent caption overlap,\r\n // fix css inconsistency across browsers\r\n // =====================================\r\n\r\n adjustCaption: function (slide) {\r\n var self = this,\r\n current = slide || self.current,\r\n caption = current.opts.caption,\r\n preventOverlap = current.opts.preventCaptionOverlap,\r\n $caption = self.$refs.caption,\r\n $clone,\r\n captionH = false;\r\n\r\n $caption.toggleClass(\"fancybox-caption--separate\", preventOverlap);\r\n\r\n if (preventOverlap && caption && caption.length) {\r\n if (current.pos !== self.currPos) {\r\n $clone = $caption.clone().appendTo($caption.parent());\r\n\r\n $clone\r\n .children()\r\n .eq(0)\r\n .empty()\r\n .html(caption);\r\n\r\n captionH = $clone.outerHeight(true);\r\n\r\n $clone.empty().remove();\r\n } else if (self.$caption) {\r\n captionH = self.$caption.outerHeight(true);\r\n }\r\n\r\n current.$slide.css(\"padding-bottom\", captionH || \"\");\r\n }\r\n },\r\n\r\n // Simple hack to fix inconsistency across browsers, described here (affects Edge, too):\r\n // https://bugzilla.mozilla.org/show_bug.cgi?id=748518\r\n // ====================================================================================\r\n\r\n adjustLayout: function (slide) {\r\n var self = this,\r\n current = slide || self.current,\r\n scrollHeight,\r\n marginBottom,\r\n inlinePadding,\r\n actualPadding;\r\n\r\n if (current.isLoaded && current.opts.disableLayoutFix !== true) {\r\n current.$content.css(\"margin-bottom\", \"\");\r\n\r\n // If we would always set margin-bottom for the content,\r\n // then it would potentially break vertical align\r\n if (current.$content.outerHeight() > current.$slide.height() + 0.5) {\r\n inlinePadding = current.$slide[0].style[\"padding-bottom\"];\r\n actualPadding = current.$slide.css(\"padding-bottom\");\r\n\r\n if (parseFloat(actualPadding) > 0) {\r\n scrollHeight = current.$slide[0].scrollHeight;\r\n\r\n current.$slide.css(\"padding-bottom\", 0);\r\n\r\n if (Math.abs(scrollHeight - current.$slide[0].scrollHeight) < 1) {\r\n marginBottom = actualPadding;\r\n }\r\n\r\n current.$slide.css(\"padding-bottom\", inlinePadding);\r\n }\r\n }\r\n\r\n current.$content.css(\"margin-bottom\", marginBottom);\r\n }\r\n },\r\n\r\n // Make content visible\r\n // This method is called right after content has been loaded or\r\n // user navigates gallery and transition should start\r\n // ============================================================\r\n\r\n revealContent: function (slide) {\r\n var self = this,\r\n $slide = slide.$slide,\r\n end = false,\r\n start = false,\r\n isMoved = self.isMoved(slide),\r\n isRevealed = slide.isRevealed,\r\n effect,\r\n effectClassName,\r\n duration,\r\n opacity;\r\n\r\n slide.isRevealed = true;\r\n\r\n effect = slide.opts[self.firstRun ? \"animationEffect\" : \"transitionEffect\"];\r\n duration = slide.opts[self.firstRun ? \"animationDuration\" : \"transitionDuration\"];\r\n\r\n duration = parseInt(slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10);\r\n\r\n if (isMoved || slide.pos !== self.currPos || !duration) {\r\n effect = false;\r\n }\r\n\r\n // Check if can zoom\r\n if (effect === \"zoom\") {\r\n if (slide.pos === self.currPos && duration && slide.type === \"image\" && !slide.hasError && (start = self.getThumbPos(slide))) {\r\n end = self.getFitPos(slide);\r\n } else {\r\n effect = \"fade\";\r\n }\r\n }\r\n\r\n // Zoom animation\r\n // ==============\r\n if (effect === \"zoom\") {\r\n self.isAnimating = true;\r\n\r\n end.scaleX = end.width / start.width;\r\n end.scaleY = end.height / start.height;\r\n\r\n // Check if we need to animate opacity\r\n opacity = slide.opts.zoomOpacity;\r\n\r\n if (opacity == \"auto\") {\r\n opacity = Math.abs(slide.width / slide.height - start.width / start.height) > 0.1;\r\n }\r\n\r\n if (opacity) {\r\n start.opacity = 0.1;\r\n end.opacity = 1;\r\n }\r\n\r\n // Draw image at start position\r\n $.fancybox.setTranslate(slide.$content.removeClass(\"fancybox-is-hidden\"), start);\r\n\r\n forceRedraw(slide.$content);\r\n\r\n // Start animation\r\n $.fancybox.animate(slide.$content, end, duration, function () {\r\n self.isAnimating = false;\r\n\r\n self.complete();\r\n });\r\n\r\n return;\r\n }\r\n\r\n self.updateSlide(slide);\r\n\r\n // Simply show content if no effect\r\n // ================================\r\n if (!effect) {\r\n slide.$content.removeClass(\"fancybox-is-hidden\");\r\n\r\n if (!isRevealed && isMoved && slide.type === \"image\" && !slide.hasError) {\r\n slide.$content.hide().fadeIn(\"fast\");\r\n }\r\n\r\n if (slide.pos === self.currPos) {\r\n self.complete();\r\n }\r\n\r\n return;\r\n }\r\n\r\n // Prepare for CSS transiton\r\n // =========================\r\n $.fancybox.stop($slide);\r\n\r\n //effectClassName = \"fancybox-animated fancybox-slide--\" + (slide.pos >= self.prevPos ? \"next\" : \"previous\") + \" fancybox-fx-\" + effect;\r\n effectClassName = \"fancybox-slide--\" + (slide.pos >= self.prevPos ? \"next\" : \"previous\") + \" fancybox-animated fancybox-fx-\" + effect;\r\n\r\n $slide.addClass(effectClassName).removeClass(\"fancybox-slide--current\"); //.addClass(effectClassName);\r\n\r\n slide.$content.removeClass(\"fancybox-is-hidden\");\r\n\r\n // Force reflow\r\n forceRedraw($slide);\r\n\r\n if (slide.type !== \"image\") {\r\n slide.$content.hide().show(0);\r\n }\r\n\r\n $.fancybox.animate(\r\n $slide,\r\n \"fancybox-slide--current\",\r\n duration,\r\n function () {\r\n $slide.removeClass(effectClassName).css({\r\n transform: \"\",\r\n opacity: \"\"\r\n });\r\n\r\n if (slide.pos === self.currPos) {\r\n self.complete();\r\n }\r\n },\r\n true\r\n );\r\n },\r\n\r\n // Check if we can and have to zoom from thumbnail\r\n //================================================\r\n\r\n getThumbPos: function (slide) {\r\n var rez = false,\r\n $thumb = slide.$thumb,\r\n thumbPos,\r\n btw,\r\n brw,\r\n bbw,\r\n blw;\r\n\r\n if (!$thumb || !inViewport($thumb[0])) {\r\n return false;\r\n }\r\n\r\n thumbPos = $.fancybox.getTranslate($thumb);\r\n\r\n btw = parseFloat($thumb.css(\"border-top-width\") || 0);\r\n brw = parseFloat($thumb.css(\"border-right-width\") || 0);\r\n bbw = parseFloat($thumb.css(\"border-bottom-width\") || 0);\r\n blw = parseFloat($thumb.css(\"border-left-width\") || 0);\r\n\r\n rez = {\r\n top: thumbPos.top + btw,\r\n left: thumbPos.left + blw,\r\n width: thumbPos.width - brw - blw,\r\n height: thumbPos.height - btw - bbw,\r\n scaleX: 1,\r\n scaleY: 1\r\n };\r\n\r\n return thumbPos.width > 0 && thumbPos.height > 0 ? rez : false;\r\n },\r\n\r\n // Final adjustments after current gallery item is moved to position\r\n // and it`s content is loaded\r\n // ==================================================================\r\n\r\n complete: function () {\r\n var self = this,\r\n current = self.current,\r\n slides = {},\r\n $el;\r\n\r\n if (self.isMoved() || !current.isLoaded) {\r\n return;\r\n }\r\n\r\n if (!current.isComplete) {\r\n current.isComplete = true;\r\n\r\n current.$slide.siblings().trigger(\"onReset\");\r\n\r\n self.preload(\"inline\");\r\n\r\n // Trigger any CSS transiton inside the slide\r\n forceRedraw(current.$slide);\r\n\r\n current.$slide.addClass(\"fancybox-slide--complete\");\r\n\r\n // Remove unnecessary slides\r\n $.each(self.slides, function (key, slide) {\r\n if (slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1) {\r\n slides[slide.pos] = slide;\r\n } else if (slide) {\r\n $.fancybox.stop(slide.$slide);\r\n\r\n slide.$slide.off().remove();\r\n }\r\n });\r\n\r\n self.slides = slides;\r\n }\r\n\r\n self.isAnimating = false;\r\n\r\n self.updateCursor();\r\n\r\n self.trigger(\"afterShow\");\r\n\r\n // Autoplay first html5 video/audio\r\n if (!!current.opts.video.autoStart) {\r\n current.$slide\r\n .find(\"video,audio\")\r\n .filter(\":visible:first\")\r\n .trigger(\"play\")\r\n .one(\"ended\", function () {\r\n if (Document.exitFullscreen) {\r\n Document.exitFullscreen();\r\n } else if (this.webkitExitFullscreen) {\r\n this.webkitExitFullscreen();\r\n }\r\n\r\n self.next();\r\n });\r\n }\r\n\r\n // Try to focus on the first focusable element\r\n if (current.opts.autoFocus && current.contentType === \"html\") {\r\n // Look for the first input with autofocus attribute\r\n $el = current.$content.find(\"input[autofocus]:enabled:visible:first\");\r\n\r\n if ($el.length) {\r\n $el.trigger(\"focus\");\r\n } else {\r\n self.focus(null, true);\r\n }\r\n }\r\n\r\n // Avoid jumping\r\n current.$slide.scrollTop(0).scrollLeft(0);\r\n },\r\n\r\n // Preload next and previous slides\r\n // ================================\r\n\r\n preload: function (type) {\r\n var self = this,\r\n prev,\r\n next;\r\n\r\n if (self.group.length < 2) {\r\n return;\r\n }\r\n\r\n next = self.slides[self.currPos + 1];\r\n prev = self.slides[self.currPos - 1];\r\n\r\n if (prev && prev.type === type) {\r\n self.loadSlide(prev);\r\n }\r\n\r\n if (next && next.type === type) {\r\n self.loadSlide(next);\r\n }\r\n },\r\n\r\n // Try to find and focus on the first focusable element\r\n // ====================================================\r\n\r\n focus: function (e, firstRun) {\r\n var self = this,\r\n focusableStr = [\r\n \"a[href]\",\r\n \"area[href]\",\r\n 'input:not([disabled]):not([type=\"hidden\"]):not([aria-hidden])',\r\n \"select:not([disabled]):not([aria-hidden])\",\r\n \"textarea:not([disabled]):not([aria-hidden])\",\r\n \"button:not([disabled]):not([aria-hidden])\",\r\n \"iframe\",\r\n \"object\",\r\n \"embed\",\r\n \"video\",\r\n \"audio\",\r\n \"[contenteditable]\",\r\n '[tabindex]:not([tabindex^=\"-\"])'\r\n ].join(\",\"),\r\n focusableItems,\r\n focusedItemIndex;\r\n\r\n if (self.isClosing) {\r\n return;\r\n }\r\n\r\n if (e || !self.current || !self.current.isComplete) {\r\n // Focus on any element inside fancybox\r\n focusableItems = self.$refs.container.find(\"*:visible\");\r\n } else {\r\n // Focus inside current slide\r\n focusableItems = self.current.$slide.find(\"*:visible\" + (firstRun ? \":not(.fancybox-close-small)\" : \"\"));\r\n }\r\n\r\n focusableItems = focusableItems.filter(focusableStr).filter(function () {\r\n return $(this).css(\"visibility\") !== \"hidden\" && !$(this).hasClass(\"disabled\");\r\n });\r\n\r\n if (focusableItems.length) {\r\n focusedItemIndex = focusableItems.index(document.activeElement);\r\n\r\n if (e && e.shiftKey) {\r\n // Back tab\r\n if (focusedItemIndex < 0 || focusedItemIndex == 0) {\r\n e.preventDefault();\r\n\r\n focusableItems.eq(focusableItems.length - 1).trigger(\"focus\");\r\n }\r\n } else {\r\n // Outside or Forward tab\r\n if (focusedItemIndex < 0 || focusedItemIndex == focusableItems.length - 1) {\r\n if (e) {\r\n e.preventDefault();\r\n }\r\n\r\n focusableItems.eq(0).trigger(\"focus\");\r\n }\r\n }\r\n } else {\r\n self.$refs.container.trigger(\"focus\");\r\n }\r\n },\r\n\r\n // Activates current instance - brings container to the front and enables keyboard,\r\n // notifies other instances about deactivating\r\n // =================================================================================\r\n\r\n activate: function () {\r\n var self = this;\r\n\r\n // Deactivate all instances\r\n $(\".fancybox-container\").each(function () {\r\n var instance = $(this).data(\"FancyBox\");\r\n\r\n // Skip self and closing instances\r\n if (instance && instance.id !== self.id && !instance.isClosing) {\r\n instance.trigger(\"onDeactivate\");\r\n\r\n instance.removeEvents();\r\n\r\n instance.isVisible = false;\r\n }\r\n });\r\n\r\n self.isVisible = true;\r\n\r\n if (self.current || self.isIdle) {\r\n self.update();\r\n\r\n self.updateControls();\r\n }\r\n\r\n self.trigger(\"onActivate\");\r\n\r\n self.addEvents();\r\n },\r\n\r\n // Start closing procedure\r\n // This will start \"zoom-out\" animation if needed and clean everything up afterwards\r\n // =================================================================================\r\n\r\n close: function (e, d) {\r\n var self = this,\r\n current = self.current,\r\n effect,\r\n duration,\r\n $content,\r\n domRect,\r\n opacity,\r\n start,\r\n end;\r\n\r\n var done = function () {\r\n self.cleanUp(e);\r\n };\r\n\r\n if (self.isClosing) {\r\n return false;\r\n }\r\n\r\n self.isClosing = true;\r\n\r\n // If beforeClose callback prevents closing, make sure content is centered\r\n if (self.trigger(\"beforeClose\", e) === false) {\r\n self.isClosing = false;\r\n\r\n requestAFrame(function () {\r\n self.update();\r\n });\r\n\r\n return false;\r\n }\r\n\r\n // Remove all events\r\n // If there are multiple instances, they will be set again by \"activate\" method\r\n self.removeEvents();\r\n\r\n $content = current.$content;\r\n effect = current.opts.animationEffect;\r\n duration = $.isNumeric(d) ? d : effect ? current.opts.animationDuration : 0;\r\n\r\n current.$slide.removeClass(\"fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated\");\r\n\r\n if (e !== true) {\r\n $.fancybox.stop(current.$slide);\r\n } else {\r\n effect = false;\r\n }\r\n\r\n // Remove other slides\r\n current.$slide\r\n .siblings()\r\n .trigger(\"onReset\")\r\n .remove();\r\n\r\n // Trigger animations\r\n if (duration) {\r\n self.$refs.container\r\n .removeClass(\"fancybox-is-open\")\r\n .addClass(\"fancybox-is-closing\")\r\n .css(\"transition-duration\", duration + \"ms\");\r\n }\r\n\r\n // Clean up\r\n self.hideLoading(current);\r\n\r\n self.hideControls(true);\r\n\r\n self.updateCursor();\r\n\r\n // Check if possible to zoom-out\r\n if (\r\n effect === \"zoom\" &&\r\n !($content && duration && current.type === \"image\" && !self.isMoved() && !current.hasError && (end = self.getThumbPos(current)))\r\n ) {\r\n effect = \"fade\";\r\n }\r\n\r\n if (effect === \"zoom\") {\r\n $.fancybox.stop($content);\r\n\r\n domRect = $.fancybox.getTranslate($content);\r\n\r\n start = {\r\n top: domRect.top,\r\n left: domRect.left,\r\n scaleX: domRect.width / end.width,\r\n scaleY: domRect.height / end.height,\r\n width: end.width,\r\n height: end.height\r\n };\r\n\r\n // Check if we need to animate opacity\r\n opacity = current.opts.zoomOpacity;\r\n\r\n if (opacity == \"auto\") {\r\n opacity = Math.abs(current.width / current.height - end.width / end.height) > 0.1;\r\n }\r\n\r\n if (opacity) {\r\n end.opacity = 0;\r\n }\r\n\r\n $.fancybox.setTranslate($content, start);\r\n\r\n forceRedraw($content);\r\n\r\n $.fancybox.animate($content, end, duration, done);\r\n\r\n return true;\r\n }\r\n\r\n if (effect && duration) {\r\n $.fancybox.animate(\r\n current.$slide.addClass(\"fancybox-slide--previous\").removeClass(\"fancybox-slide--current\"),\r\n \"fancybox-animated fancybox-fx-\" + effect,\r\n duration,\r\n done\r\n );\r\n } else {\r\n // If skip animation\r\n if (e === true) {\r\n setTimeout(done, duration);\r\n } else {\r\n done();\r\n }\r\n }\r\n\r\n return true;\r\n },\r\n\r\n // Final adjustments after removing the instance\r\n // =============================================\r\n\r\n cleanUp: function (e) {\r\n var self = this,\r\n instance,\r\n $focus = self.current.opts.$orig,\r\n x,\r\n y;\r\n\r\n self.current.$slide.trigger(\"onReset\");\r\n\r\n self.$refs.container.empty().remove();\r\n\r\n self.trigger(\"afterClose\", e);\r\n\r\n // Place back focus\r\n if (!!self.current.opts.backFocus) {\r\n if (!$focus || !$focus.length || !$focus.is(\":visible\")) {\r\n $focus = self.$trigger;\r\n }\r\n\r\n if ($focus && $focus.length) {\r\n x = window.scrollX;\r\n y = window.scrollY;\r\n\r\n $focus.trigger(\"focus\");\r\n\r\n $(\"html, body\")\r\n .scrollTop(y)\r\n .scrollLeft(x);\r\n }\r\n }\r\n\r\n self.current = null;\r\n\r\n // Check if there are other instances\r\n instance = $.fancybox.getInstance();\r\n\r\n if (instance) {\r\n instance.activate();\r\n } else {\r\n $(\"body\").removeClass(\"fancybox-active compensate-for-scrollbar\");\r\n\r\n $(\"#fancybox-style-noscroll\").remove();\r\n }\r\n },\r\n\r\n // Call callback and trigger an event\r\n // ==================================\r\n\r\n trigger: function (name, slide) {\r\n var args = Array.prototype.slice.call(arguments, 1),\r\n self = this,\r\n obj = slide && slide.opts ? slide : self.current,\r\n rez;\r\n\r\n if (obj) {\r\n args.unshift(obj);\r\n } else {\r\n obj = self;\r\n }\r\n\r\n args.unshift(self);\r\n\r\n if ($.isFunction(obj.opts[name])) {\r\n rez = obj.opts[name].apply(obj, args);\r\n }\r\n\r\n if (rez === false) {\r\n return rez;\r\n }\r\n\r\n if (name === \"afterClose\" || !self.$refs) {\r\n $D.trigger(name + \".fb\", args);\r\n } else {\r\n self.$refs.container.trigger(name + \".fb\", args);\r\n }\r\n },\r\n\r\n // Update infobar values, navigation button states and reveal caption\r\n // ==================================================================\r\n\r\n updateControls: function () {\r\n var self = this,\r\n current = self.current,\r\n index = current.index,\r\n $container = self.$refs.container,\r\n $caption = self.$refs.caption,\r\n caption = current.opts.caption;\r\n\r\n // Recalculate content dimensions\r\n current.$slide.trigger(\"refresh\");\r\n\r\n // Set caption\r\n if (caption && caption.length) {\r\n self.$caption = $caption;\r\n\r\n $caption\r\n .children()\r\n .eq(0)\r\n .html(caption);\r\n } else {\r\n self.$caption = null;\r\n }\r\n\r\n if (!self.hasHiddenControls && !self.isIdle) {\r\n self.showControls();\r\n }\r\n\r\n // Update info and navigation elements\r\n $container.find(\"[data-fancybox-count]\").html(self.group.length);\r\n $container.find(\"[data-fancybox-index]\").html(index + 1);\r\n\r\n $container.find(\"[data-fancybox-prev]\").prop(\"disabled\", !current.opts.loop && index <= 0);\r\n $container.find(\"[data-fancybox-next]\").prop(\"disabled\", !current.opts.loop && index >= self.group.length - 1);\r\n\r\n if (current.type === \"image\") {\r\n // Re-enable buttons; update download button source\r\n $container\r\n .find(\"[data-fancybox-zoom]\")\r\n .show()\r\n .end()\r\n .find(\"[data-fancybox-download]\")\r\n .attr(\"href\", current.opts.image.src || current.src)\r\n .show();\r\n } else if (current.opts.toolbar) {\r\n $container.find(\"[data-fancybox-download],[data-fancybox-zoom]\").hide();\r\n }\r\n\r\n // Make sure focus is not on disabled button/element\r\n if ($(document.activeElement).is(\":hidden,[disabled]\")) {\r\n self.$refs.container.trigger(\"focus\");\r\n }\r\n },\r\n\r\n // Hide toolbar and caption\r\n // ========================\r\n\r\n hideControls: function (andCaption) {\r\n var self = this,\r\n arr = [\"infobar\", \"toolbar\", \"nav\"];\r\n\r\n if (andCaption || !self.current.opts.preventCaptionOverlap) {\r\n arr.push(\"caption\");\r\n }\r\n\r\n this.$refs.container.removeClass(\r\n arr\r\n .map(function (i) {\r\n return \"fancybox-show-\" + i;\r\n })\r\n .join(\" \")\r\n );\r\n\r\n this.hasHiddenControls = true;\r\n },\r\n\r\n showControls: function () {\r\n var self = this,\r\n opts = self.current ? self.current.opts : self.opts,\r\n $container = self.$refs.container;\r\n\r\n self.hasHiddenControls = false;\r\n self.idleSecondsCounter = 0;\r\n\r\n $container\r\n .toggleClass(\"fancybox-show-toolbar\", !!(opts.toolbar && opts.buttons))\r\n .toggleClass(\"fancybox-show-infobar\", !!(opts.infobar && self.group.length > 1))\r\n .toggleClass(\"fancybox-show-caption\", !!self.$caption)\r\n .toggleClass(\"fancybox-show-nav\", !!(opts.arrows && self.group.length > 1))\r\n .toggleClass(\"fancybox-is-modal\", !!opts.modal);\r\n },\r\n\r\n // Toggle toolbar and caption\r\n // ==========================\r\n\r\n toggleControls: function () {\r\n if (this.hasHiddenControls) {\r\n this.showControls();\r\n } else {\r\n this.hideControls();\r\n }\r\n }\r\n });\r\n\r\n $.fancybox = {\r\n version: \"3.5.7\",\r\n defaults: defaults,\r\n\r\n // Get current instance and execute a command.\r\n //\r\n // Examples of usage:\r\n //\r\n // $instance = $.fancybox.getInstance();\r\n // $.fancybox.getInstance().jumpTo( 1 );\r\n // $.fancybox.getInstance( 'jumpTo', 1 );\r\n // $.fancybox.getInstance( function() {\r\n // console.info( this.currIndex );\r\n // });\r\n // ======================================================\r\n\r\n getInstance: function (command) {\r\n var instance = $('.fancybox-container:not(\".fancybox-is-closing\"):last').data(\"FancyBox\"),\r\n args = Array.prototype.slice.call(arguments, 1);\r\n\r\n if (instance instanceof FancyBox) {\r\n if ($.type(command) === \"string\") {\r\n instance[command].apply(instance, args);\r\n } else if ($.type(command) === \"function\") {\r\n command.apply(instance, args);\r\n }\r\n\r\n return instance;\r\n }\r\n\r\n return false;\r\n },\r\n\r\n // Create new instance\r\n // ===================\r\n\r\n open: function (items, opts, index) {\r\n return new FancyBox(items, opts, index);\r\n },\r\n\r\n // Close current or all instances\r\n // ==============================\r\n\r\n close: function (all) {\r\n var instance = this.getInstance();\r\n\r\n if (instance) {\r\n instance.close();\r\n\r\n // Try to find and close next instance\r\n if (all === true) {\r\n this.close(all);\r\n }\r\n }\r\n },\r\n\r\n // Close all instances and unbind all events\r\n // =========================================\r\n\r\n destroy: function () {\r\n this.close(true);\r\n\r\n $D.add(\"body\").off(\"click.fb-start\", \"**\");\r\n },\r\n\r\n // Try to detect mobile devices\r\n // ============================\r\n\r\n isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),\r\n\r\n // Detect if 'translate3d' support is available\r\n // ============================================\r\n\r\n use3d: (function () {\r\n var div = document.createElement(\"div\");\r\n\r\n return (\r\n window.getComputedStyle &&\r\n window.getComputedStyle(div) &&\r\n window.getComputedStyle(div).getPropertyValue(\"transform\") &&\r\n !(document.documentMode && document.documentMode < 11)\r\n );\r\n })(),\r\n\r\n // Helper function to get current visual state of an element\r\n // returns array[ top, left, horizontal-scale, vertical-scale, opacity ]\r\n // =====================================================================\r\n\r\n getTranslate: function ($el) {\r\n var domRect;\r\n\r\n if (!$el || !$el.length) {\r\n return false;\r\n }\r\n\r\n domRect = $el[0].getBoundingClientRect();\r\n\r\n return {\r\n top: domRect.top || 0,\r\n left: domRect.left || 0,\r\n width: domRect.width,\r\n height: domRect.height,\r\n opacity: parseFloat($el.css(\"opacity\"))\r\n };\r\n },\r\n\r\n // Shortcut for setting \"translate3d\" properties for element\r\n // Can set be used to set opacity, too\r\n // ========================================================\r\n\r\n setTranslate: function ($el, props) {\r\n var str = \"\",\r\n css = {};\r\n\r\n if (!$el || !props) {\r\n return;\r\n }\r\n\r\n if (props.left !== undefined || props.top !== undefined) {\r\n str =\r\n (props.left === undefined ? $el.position().left : props.left) +\r\n \"px, \" +\r\n (props.top === undefined ? $el.position().top : props.top) +\r\n \"px\";\r\n\r\n if (this.use3d) {\r\n str = \"translate3d(\" + str + \", 0px)\";\r\n } else {\r\n str = \"translate(\" + str + \")\";\r\n }\r\n }\r\n\r\n if (props.scaleX !== undefined && props.scaleY !== undefined) {\r\n str += \" scale(\" + props.scaleX + \", \" + props.scaleY + \")\";\r\n } else if (props.scaleX !== undefined) {\r\n str += \" scaleX(\" + props.scaleX + \")\";\r\n }\r\n\r\n if (str.length) {\r\n css.transform = str;\r\n }\r\n\r\n if (props.opacity !== undefined) {\r\n css.opacity = props.opacity;\r\n }\r\n\r\n if (props.width !== undefined) {\r\n css.width = props.width;\r\n }\r\n\r\n if (props.height !== undefined) {\r\n css.height = props.height;\r\n }\r\n\r\n return $el.css(css);\r\n },\r\n\r\n // Simple CSS transition handler\r\n // =============================\r\n\r\n animate: function ($el, to, duration, callback, leaveAnimationName) {\r\n var self = this,\r\n from;\r\n\r\n if ($.isFunction(duration)) {\r\n callback = duration;\r\n duration = null;\r\n }\r\n\r\n self.stop($el);\r\n\r\n from = self.getTranslate($el);\r\n\r\n $el.on(transitionEnd, function (e) {\r\n // Skip events from child elements and z-index change\r\n if (e && e.originalEvent && (!$el.is(e.originalEvent.target) || e.originalEvent.propertyName == \"z-index\")) {\r\n return;\r\n }\r\n\r\n self.stop($el);\r\n\r\n if ($.isNumeric(duration)) {\r\n $el.css(\"transition-duration\", \"\");\r\n }\r\n\r\n if ($.isPlainObject(to)) {\r\n if (to.scaleX !== undefined && to.scaleY !== undefined) {\r\n self.setTranslate($el, {\r\n top: to.top,\r\n left: to.left,\r\n width: from.width * to.scaleX,\r\n height: from.height * to.scaleY,\r\n scaleX: 1,\r\n scaleY: 1\r\n });\r\n }\r\n } else if (leaveAnimationName !== true) {\r\n $el.removeClass(to);\r\n }\r\n\r\n if ($.isFunction(callback)) {\r\n callback(e);\r\n }\r\n });\r\n\r\n if ($.isNumeric(duration)) {\r\n $el.css(\"transition-duration\", duration + \"ms\");\r\n }\r\n\r\n // Start animation by changing CSS properties or class name\r\n if ($.isPlainObject(to)) {\r\n if (to.scaleX !== undefined && to.scaleY !== undefined) {\r\n delete to.width;\r\n delete to.height;\r\n\r\n if ($el.parent().hasClass(\"fancybox-slide--image\")) {\r\n $el.parent().addClass(\"fancybox-is-scaling\");\r\n }\r\n }\r\n\r\n $.fancybox.setTranslate($el, to);\r\n } else {\r\n $el.addClass(to);\r\n }\r\n\r\n // Make sure that `transitionend` callback gets fired\r\n $el.data(\r\n \"timer\",\r\n setTimeout(function () {\r\n $el.trigger(transitionEnd);\r\n }, duration + 33)\r\n );\r\n },\r\n\r\n stop: function ($el, callCallback) {\r\n if ($el && $el.length) {\r\n clearTimeout($el.data(\"timer\"));\r\n\r\n if (callCallback) {\r\n $el.trigger(transitionEnd);\r\n }\r\n\r\n $el.off(transitionEnd).css(\"transition-duration\", \"\");\r\n\r\n $el.parent().removeClass(\"fancybox-is-scaling\");\r\n }\r\n }\r\n };\r\n\r\n // Default click handler for \"fancyboxed\" links\r\n // ============================================\r\n\r\n function _run(e, opts) {\r\n var items = [],\r\n index = 0,\r\n $target,\r\n value,\r\n instance;\r\n\r\n // Avoid opening multiple times\r\n if (e && e.isDefaultPrevented()) {\r\n return;\r\n }\r\n\r\n e.preventDefault();\r\n\r\n opts = opts || {};\r\n\r\n if (e && e.data) {\r\n opts = mergeOpts(e.data.options, opts);\r\n }\r\n\r\n $target = opts.$target || $(e.currentTarget).trigger(\"blur\");\r\n instance = $.fancybox.getInstance();\r\n\r\n if (instance && instance.$trigger && instance.$trigger.is($target)) {\r\n return;\r\n }\r\n\r\n if (opts.selector) {\r\n items = $(opts.selector);\r\n } else {\r\n // Get all related items and find index for clicked one\r\n value = $target.attr(\"data-fancybox\") || \"\";\r\n\r\n if (value) {\r\n items = e.data ? e.data.items : [];\r\n items = items.length ? items.filter('[data-fancybox=\"' + value + '\"]') : $('[data-fancybox=\"' + value + '\"]');\r\n } else {\r\n items = [$target];\r\n }\r\n }\r\n\r\n index = $(items).index($target);\r\n\r\n // Sometimes current item can not be found\r\n if (index < 0) {\r\n index = 0;\r\n }\r\n\r\n instance = $.fancybox.open(items, opts, index);\r\n\r\n // Save last active element\r\n instance.$trigger = $target;\r\n }\r\n\r\n // Create a jQuery plugin\r\n // ======================\r\n\r\n $.fn.fancybox = function (options) {\r\n var selector;\r\n\r\n options = options || {};\r\n selector = options.selector || false;\r\n\r\n if (selector) {\r\n // Use body element instead of document so it executes first\r\n $(\"body\")\r\n .off(\"click.fb-start\", selector)\r\n .on(\"click.fb-start\", selector, {\r\n options: options\r\n }, _run);\r\n } else {\r\n this.off(\"click.fb-start\").on(\r\n \"click.fb-start\", {\r\n items: this,\r\n options: options\r\n },\r\n _run\r\n );\r\n }\r\n\r\n return this;\r\n };\r\n\r\n // Self initializing plugin for all elements having `data-fancybox` attribute\r\n // ==========================================================================\r\n\r\n $D.on(\"click.fb-start\", \"[data-fancybox]\", _run);\r\n\r\n // Enable \"trigger elements\"\r\n // =========================\r\n\r\n $D.on(\"click.fb-start\", \"[data-fancybox-trigger]\", function (e) {\r\n $('[data-fancybox=\"' + $(this).attr(\"data-fancybox-trigger\") + '\"]')\r\n .eq($(this).attr(\"data-fancybox-index\") || 0)\r\n .trigger(\"click.fb-start\", {\r\n $trigger: $(this)\r\n });\r\n });\r\n\r\n // Track focus event for better accessibility styling\r\n // ==================================================\r\n (function () {\r\n var buttonStr = \".fancybox-button\",\r\n focusStr = \"fancybox-focus\",\r\n $pressed = null;\r\n\r\n $D.on(\"mousedown mouseup focus blur\", buttonStr, function (e) {\r\n switch (e.type) {\r\n case \"mousedown\":\r\n $pressed = $(this);\r\n break;\r\n case \"mouseup\":\r\n $pressed = null;\r\n break;\r\n case \"focusin\":\r\n $(buttonStr).removeClass(focusStr);\r\n\r\n if (!$(this).is($pressed) && !$(this).is(\"[disabled]\")) {\r\n $(this).addClass(focusStr);\r\n }\r\n break;\r\n case \"focusout\":\r\n $(buttonStr).removeClass(focusStr);\r\n break;\r\n }\r\n });\r\n })();\r\n})(window, document, jQuery);\n// ==========================================================================\r\n//\r\n// Media\r\n// Adds additional media type support\r\n//\r\n// ==========================================================================\r\n(function ($) {\r\n \"use strict\";\r\n\r\n // Object containing properties for each media type\r\n var defaults = {\r\n youtube: {\r\n matcher: /(youtube\\.com|youtu\\.be|youtube\\-nocookie\\.com)\\/(watch\\?(.*&)?v=|v\\/|u\\/|embed\\/?)?(videoseries\\?list=(.*)|[\\w-]{11}|\\?listType=(.*)&list=(.*))(.*)/i,\r\n params: {\r\n autoplay: 1,\r\n autohide: 1,\r\n fs: 1,\r\n rel: 0,\r\n hd: 1,\r\n wmode: \"transparent\",\r\n enablejsapi: 1,\r\n html5: 1\r\n },\r\n paramPlace: 8,\r\n type: \"iframe\",\r\n url: \"https://www.youtube-nocookie.com/embed/$4\",\r\n thumb: \"https://img.youtube.com/vi/$4/hqdefault.jpg\"\r\n },\r\n\r\n vimeo: {\r\n matcher: /^.+vimeo.com\\/(.*\\/)?([\\d]+)(.*)?/,\r\n params: {\r\n autoplay: 1,\r\n hd: 1,\r\n show_title: 1,\r\n show_byline: 1,\r\n show_portrait: 0,\r\n fullscreen: 1\r\n },\r\n paramPlace: 3,\r\n type: \"iframe\",\r\n url: \"//player.vimeo.com/video/$2\"\r\n },\r\n\r\n instagram: {\r\n matcher: /(instagr\\.am|instagram\\.com)\\/p\\/([a-zA-Z0-9_\\-]+)\\/?/i,\r\n type: \"image\",\r\n url: \"//$1/p/$2/media/?size=l\"\r\n },\r\n\r\n // Examples:\r\n // http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16\r\n // https://www.google.com/maps/@37.7852006,-122.4146355,14.65z\r\n // https://www.google.com/maps/@52.2111123,2.9237542,6.61z?hl=en\r\n // https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572\r\n gmap_place: {\r\n matcher: /(maps\\.)?google\\.([a-z]{2,3}(\\.[a-z]{2})?)\\/(((maps\\/(place\\/(.*)\\/)?\\@(.*),(\\d+.?\\d+?)z))|(\\?ll=))(.*)?/i,\r\n type: \"iframe\",\r\n url: function (rez) {\r\n return (\r\n \"//maps.google.\" +\r\n rez[2] +\r\n \"/?ll=\" +\r\n (rez[9] ? rez[9] + \"&z=\" + Math.floor(rez[10]) + (rez[12] ? rez[12].replace(/^\\//, \"&\") : \"\") : rez[12] + \"\").replace(/\\?/, \"&\") +\r\n \"&output=\" +\r\n (rez[12] && rez[12].indexOf(\"layer=c\") > 0 ? \"svembed\" : \"embed\")\r\n );\r\n }\r\n },\r\n\r\n // Examples:\r\n // https://www.google.com/maps/search/Empire+State+Building/\r\n // https://www.google.com/maps/search/?api=1&query=centurylink+field\r\n // https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393\r\n gmap_search: {\r\n matcher: /(maps\\.)?google\\.([a-z]{2,3}(\\.[a-z]{2})?)\\/(maps\\/search\\/)(.*)/i,\r\n type: \"iframe\",\r\n url: function (rez) {\r\n return \"//maps.google.\" + rez[2] + \"/maps?q=\" + rez[5].replace(\"query=\", \"q=\").replace(\"api=1\", \"\") + \"&output=embed\";\r\n }\r\n }\r\n };\r\n\r\n // Formats matching url to final form\r\n var format = function (url, rez, params) {\r\n if (!url) {\r\n return;\r\n }\r\n\r\n params = params || \"\";\r\n\r\n if ($.type(params) === \"object\") {\r\n params = $.param(params, true);\r\n }\r\n\r\n $.each(rez, function (key, value) {\r\n url = url.replace(\"$\" + key, value || \"\");\r\n });\r\n\r\n if (params.length) {\r\n url += (url.indexOf(\"?\") > 0 ? \"&\" : \"?\") + params;\r\n }\r\n\r\n return url;\r\n };\r\n\r\n $(document).on(\"objectNeedsType.fb\", function (e, instance, item) {\r\n var url = item.src || \"\",\r\n type = false,\r\n media,\r\n thumb,\r\n rez,\r\n params,\r\n urlParams,\r\n paramObj,\r\n provider;\r\n\r\n media = $.extend(true, {}, defaults, item.opts.media);\r\n\r\n // Look for any matching media type\r\n $.each(media, function (providerName, providerOpts) {\r\n rez = url.match(providerOpts.matcher);\r\n\r\n if (!rez) {\r\n return;\r\n }\r\n\r\n type = providerOpts.type;\r\n provider = providerName;\r\n paramObj = {};\r\n\r\n if (providerOpts.paramPlace && rez[providerOpts.paramPlace]) {\r\n urlParams = rez[providerOpts.paramPlace];\r\n\r\n if (urlParams[0] == \"?\") {\r\n urlParams = urlParams.substring(1);\r\n }\r\n\r\n urlParams = urlParams.split(\"&\");\r\n\r\n for (var m = 0; m < urlParams.length; ++m) {\r\n var p = urlParams[m].split(\"=\", 2);\r\n\r\n if (p.length == 2) {\r\n paramObj[p[0]] = decodeURIComponent(p[1].replace(/\\+/g, \" \"));\r\n }\r\n }\r\n }\r\n\r\n params = $.extend(true, {}, providerOpts.params, item.opts[providerName], paramObj);\r\n\r\n url =\r\n $.type(providerOpts.url) === \"function\" ? providerOpts.url.call(this, rez, params, item) : format(providerOpts.url, rez, params);\r\n\r\n thumb =\r\n $.type(providerOpts.thumb) === \"function\" ? providerOpts.thumb.call(this, rez, params, item) : format(providerOpts.thumb, rez);\r\n\r\n if (providerName === \"youtube\") {\r\n url = url.replace(/&t=((\\d+)m)?(\\d+)s/, function (match, p1, m, s) {\r\n return \"&start=\" + ((m ? parseInt(m, 10) * 60 : 0) + parseInt(s, 10));\r\n });\r\n } else if (providerName === \"vimeo\") {\r\n url = url.replace(\"&%23\", \"#\");\r\n }\r\n\r\n return false;\r\n });\r\n\r\n // If it is found, then change content type and update the url\r\n\r\n if (type) {\r\n if (!item.opts.thumb && !(item.opts.$thumb && item.opts.$thumb.length)) {\r\n item.opts.thumb = thumb;\r\n }\r\n\r\n if (type === \"iframe\") {\r\n item.opts = $.extend(true, item.opts, {\r\n iframe: {\r\n preload: false,\r\n attr: {\r\n scrolling: \"no\"\r\n }\r\n }\r\n });\r\n }\r\n\r\n $.extend(item, {\r\n type: type,\r\n src: url,\r\n origSrc: item.src,\r\n contentSource: provider,\r\n contentType: type === \"image\" ? \"image\" : provider == \"gmap_place\" || provider == \"gmap_search\" ? \"map\" : \"video\"\r\n });\r\n } else if (url) {\r\n item.type = item.opts.defaultType;\r\n }\r\n });\r\n\r\n // Load YouTube/Video API on request to detect when video finished playing\r\n var VideoAPILoader = {\r\n youtube: {\r\n src: \"https://www.youtube.com/iframe_api\",\r\n class: \"YT\",\r\n loading: false,\r\n loaded: false\r\n },\r\n\r\n vimeo: {\r\n src: \"https://player.vimeo.com/api/player.js\",\r\n class: \"Vimeo\",\r\n loading: false,\r\n loaded: false\r\n },\r\n\r\n load: function (vendor) {\r\n var _this = this,\r\n script;\r\n\r\n if (this[vendor].loaded) {\r\n setTimeout(function () {\r\n _this.done(vendor);\r\n });\r\n return;\r\n }\r\n\r\n if (this[vendor].loading) {\r\n return;\r\n }\r\n\r\n this[vendor].loading = true;\r\n\r\n script = document.createElement(\"script\");\r\n script.type = \"text/javascript\";\r\n script.src = this[vendor].src;\r\n\r\n if (vendor === \"youtube\") {\r\n window.onYouTubeIframeAPIReady = function () {\r\n _this[vendor].loaded = true;\r\n _this.done(vendor);\r\n };\r\n } else {\r\n script.onload = function () {\r\n _this[vendor].loaded = true;\r\n _this.done(vendor);\r\n };\r\n }\r\n\r\n document.body.appendChild(script);\r\n },\r\n done: function (vendor) {\r\n var instance, $el, player;\r\n\r\n if (vendor === \"youtube\") {\r\n delete window.onYouTubeIframeAPIReady;\r\n }\r\n\r\n instance = $.fancybox.getInstance();\r\n\r\n if (instance) {\r\n $el = instance.current.$content.find(\"iframe\");\r\n\r\n if (vendor === \"youtube\" && YT !== undefined && YT) {\r\n player = new YT.Player($el.attr(\"id\"), {\r\n events: {\r\n onStateChange: function (e) {\r\n if (e.data == 0) {\r\n instance.next();\r\n }\r\n }\r\n }\r\n });\r\n } else if (vendor === \"vimeo\" && Vimeo !== undefined && Vimeo) {\r\n player = new Vimeo.Player($el);\r\n\r\n player.on(\"ended\", function () {\r\n instance.next();\r\n });\r\n }\r\n }\r\n }\r\n };\r\n\r\n $(document).on({\r\n \"afterShow.fb\": function (e, instance, current) {\r\n if (instance.group.length > 1 && (current.contentSource === \"youtube\" || current.contentSource === \"vimeo\")) {\r\n VideoAPILoader.load(current.contentSource);\r\n }\r\n }\r\n });\r\n})(jQuery);\n// ==========================================================================\r\n//\r\n// Guestures\r\n// Adds touch guestures, handles click and tap events\r\n//\r\n// ==========================================================================\r\n(function (window, document, $) {\r\n \"use strict\";\r\n\r\n var requestAFrame = (function () {\r\n return (\r\n window.requestAnimationFrame ||\r\n window.webkitRequestAnimationFrame ||\r\n window.mozRequestAnimationFrame ||\r\n window.oRequestAnimationFrame ||\r\n // if all else fails, use setTimeout\r\n function (callback) {\r\n return window.setTimeout(callback, 1000 / 60);\r\n }\r\n );\r\n })();\r\n\r\n var cancelAFrame = (function () {\r\n return (\r\n window.cancelAnimationFrame ||\r\n window.webkitCancelAnimationFrame ||\r\n window.mozCancelAnimationFrame ||\r\n window.oCancelAnimationFrame ||\r\n function (id) {\r\n window.clearTimeout(id);\r\n }\r\n );\r\n })();\r\n\r\n var getPointerXY = function (e) {\r\n var result = [];\r\n\r\n e = e.originalEvent || e || window.e;\r\n e = e.touches && e.touches.length ? e.touches : e.changedTouches && e.changedTouches.length ? e.changedTouches : [e];\r\n\r\n for (var key in e) {\r\n if (e[key].pageX) {\r\n result.push({\r\n x: e[key].pageX,\r\n y: e[key].pageY\r\n });\r\n } else if (e[key].clientX) {\r\n result.push({\r\n x: e[key].clientX,\r\n y: e[key].clientY\r\n });\r\n }\r\n }\r\n\r\n return result;\r\n };\r\n\r\n var distance = function (point2, point1, what) {\r\n if (!point1 || !point2) {\r\n return 0;\r\n }\r\n\r\n if (what === \"x\") {\r\n return point2.x - point1.x;\r\n } else if (what === \"y\") {\r\n return point2.y - point1.y;\r\n }\r\n\r\n return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));\r\n };\r\n\r\n var isClickable = function ($el) {\r\n if (\r\n $el.is('a,area,button,[role=\"button\"],input,label,select,summary,textarea,video,audio,iframe') ||\r\n $.isFunction($el.get(0).onclick) ||\r\n $el.data(\"selectable\")\r\n ) {\r\n return true;\r\n }\r\n\r\n // Check for attributes like data-fancybox-next or data-fancybox-close\r\n for (var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++) {\r\n if (atts[i].nodeName.substr(0, 14) === \"data-fancybox-\") {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n };\r\n\r\n var hasScrollbars = function (el) {\r\n var overflowY = window.getComputedStyle(el)[\"overflow-y\"],\r\n overflowX = window.getComputedStyle(el)[\"overflow-x\"],\r\n vertical = (overflowY === \"scroll\" || overflowY === \"auto\") && el.scrollHeight > el.clientHeight,\r\n horizontal = (overflowX === \"scroll\" || overflowX === \"auto\") && el.scrollWidth > el.clientWidth;\r\n\r\n return vertical || horizontal;\r\n };\r\n\r\n var isScrollable = function ($el) {\r\n var rez = false;\r\n\r\n while (true) {\r\n rez = hasScrollbars($el.get(0));\r\n\r\n if (rez) {\r\n break;\r\n }\r\n\r\n $el = $el.parent();\r\n\r\n if (!$el.length || $el.hasClass(\"fancybox-stage\") || $el.is(\"body\")) {\r\n break;\r\n }\r\n }\r\n\r\n return rez;\r\n };\r\n\r\n var Guestures = function (instance) {\r\n var self = this;\r\n\r\n self.instance = instance;\r\n\r\n self.$bg = instance.$refs.bg;\r\n self.$stage = instance.$refs.stage;\r\n self.$container = instance.$refs.container;\r\n\r\n self.destroy();\r\n\r\n self.$container.on(\"touchstart.fb.touch mousedown.fb.touch\", $.proxy(self, \"ontouchstart\"));\r\n };\r\n\r\n Guestures.prototype.destroy = function () {\r\n var self = this;\r\n\r\n self.$container.off(\".fb.touch\");\r\n\r\n $(document).off(\".fb.touch\");\r\n\r\n if (self.requestId) {\r\n cancelAFrame(self.requestId);\r\n self.requestId = null;\r\n }\r\n\r\n if (self.tapped) {\r\n clearTimeout(self.tapped);\r\n self.tapped = null;\r\n }\r\n };\r\n\r\n Guestures.prototype.ontouchstart = function (e) {\r\n var self = this,\r\n $target = $(e.target),\r\n instance = self.instance,\r\n current = instance.current,\r\n $slide = current.$slide,\r\n $content = current.$content,\r\n isTouchDevice = e.type == \"touchstart\";\r\n\r\n // Do not respond to both (touch and mouse) events\r\n if (isTouchDevice) {\r\n self.$container.off(\"mousedown.fb.touch\");\r\n }\r\n\r\n // Ignore right click\r\n if (e.originalEvent && e.originalEvent.button == 2) {\r\n return;\r\n }\r\n\r\n // Ignore taping on links, buttons, input elements\r\n if (!$slide.length || !$target.length || isClickable($target) || isClickable($target.parent())) {\r\n return;\r\n }\r\n // Ignore clicks on the scrollbar\r\n if (!$target.is(\"img\") && e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left) {\r\n return;\r\n }\r\n\r\n // Ignore clicks while zooming or closing\r\n if (!current || instance.isAnimating || current.$slide.hasClass(\"fancybox-animated\")) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n\r\n return;\r\n }\r\n\r\n self.realPoints = self.startPoints = getPointerXY(e);\r\n\r\n if (!self.startPoints.length) {\r\n return;\r\n }\r\n\r\n // Allow other scripts to catch touch event if \"touch\" is set to false\r\n if (current.touch) {\r\n e.stopPropagation();\r\n }\r\n\r\n self.startEvent = e;\r\n\r\n self.canTap = true;\r\n self.$target = $target;\r\n self.$content = $content;\r\n self.opts = current.opts.touch;\r\n\r\n self.isPanning = false;\r\n self.isSwiping = false;\r\n self.isZooming = false;\r\n self.isScrolling = false;\r\n self.canPan = instance.canPan();\r\n\r\n self.startTime = new Date().getTime();\r\n self.distanceX = self.distanceY = self.distance = 0;\r\n\r\n self.canvasWidth = Math.round($slide[0].clientWidth);\r\n self.canvasHeight = Math.round($slide[0].clientHeight);\r\n\r\n self.contentLastPos = null;\r\n self.contentStartPos = $.fancybox.getTranslate(self.$content) || {\r\n top: 0,\r\n left: 0\r\n };\r\n self.sliderStartPos = $.fancybox.getTranslate($slide);\r\n\r\n // Since position will be absolute, but we need to make it relative to the stage\r\n self.stagePos = $.fancybox.getTranslate(instance.$refs.stage);\r\n\r\n self.sliderStartPos.top -= self.stagePos.top;\r\n self.sliderStartPos.left -= self.stagePos.left;\r\n\r\n self.contentStartPos.top -= self.stagePos.top;\r\n self.contentStartPos.left -= self.stagePos.left;\r\n\r\n $(document)\r\n .off(\".fb.touch\")\r\n .on(isTouchDevice ? \"touchend.fb.touch touchcancel.fb.touch\" : \"mouseup.fb.touch mouseleave.fb.touch\", $.proxy(self, \"ontouchend\"))\r\n .on(isTouchDevice ? \"touchmove.fb.touch\" : \"mousemove.fb.touch\", $.proxy(self, \"ontouchmove\"));\r\n\r\n if ($.fancybox.isMobile) {\r\n document.addEventListener(\"scroll\", self.onscroll, true);\r\n }\r\n\r\n // Skip if clicked outside the sliding area\r\n if (!(self.opts || self.canPan) || !($target.is(self.$stage) || self.$stage.find($target).length)) {\r\n if ($target.is(\".fancybox-image\")) {\r\n e.preventDefault();\r\n }\r\n\r\n if (!($.fancybox.isMobile && $target.parents(\".fancybox-caption\").length)) {\r\n return;\r\n }\r\n }\r\n\r\n self.isScrollable = isScrollable($target) || isScrollable($target.parent());\r\n\r\n // Check if element is scrollable and try to prevent default behavior (scrolling)\r\n if (!($.fancybox.isMobile && self.isScrollable)) {\r\n e.preventDefault();\r\n }\r\n\r\n // One finger or mouse click - swipe or pan an image\r\n if (self.startPoints.length === 1 || current.hasError) {\r\n if (self.canPan) {\r\n $.fancybox.stop(self.$content);\r\n\r\n self.isPanning = true;\r\n } else {\r\n self.isSwiping = true;\r\n }\r\n\r\n self.$container.addClass(\"fancybox-is-grabbing\");\r\n }\r\n\r\n // Two fingers - zoom image\r\n if (self.startPoints.length === 2 && current.type === \"image\" && (current.isLoaded || current.$ghost)) {\r\n self.canTap = false;\r\n self.isSwiping = false;\r\n self.isPanning = false;\r\n\r\n self.isZooming = true;\r\n\r\n $.fancybox.stop(self.$content);\r\n\r\n self.centerPointStartX = (self.startPoints[0].x + self.startPoints[1].x) * 0.5 - $(window).scrollLeft();\r\n self.centerPointStartY = (self.startPoints[0].y + self.startPoints[1].y) * 0.5 - $(window).scrollTop();\r\n\r\n self.percentageOfImageAtPinchPointX = (self.centerPointStartX - self.contentStartPos.left) / self.contentStartPos.width;\r\n self.percentageOfImageAtPinchPointY = (self.centerPointStartY - self.contentStartPos.top) / self.contentStartPos.height;\r\n\r\n self.startDistanceBetweenFingers = distance(self.startPoints[0], self.startPoints[1]);\r\n }\r\n };\r\n\r\n Guestures.prototype.onscroll = function (e) {\r\n var self = this;\r\n\r\n self.isScrolling = true;\r\n\r\n document.removeEventListener(\"scroll\", self.onscroll, true);\r\n };\r\n\r\n Guestures.prototype.ontouchmove = function (e) {\r\n var self = this;\r\n\r\n // Make sure user has not released over iframe or disabled element\r\n if (e.originalEvent.buttons !== undefined && e.originalEvent.buttons === 0) {\r\n self.ontouchend(e);\r\n return;\r\n }\r\n\r\n if (self.isScrolling) {\r\n self.canTap = false;\r\n return;\r\n }\r\n\r\n self.newPoints = getPointerXY(e);\r\n\r\n if (!(self.opts || self.canPan) || !self.newPoints.length || !self.newPoints.length) {\r\n return;\r\n }\r\n\r\n if (!(self.isSwiping && self.isSwiping === true)) {\r\n e.preventDefault();\r\n }\r\n\r\n self.distanceX = distance(self.newPoints[0], self.startPoints[0], \"x\");\r\n self.distanceY = distance(self.newPoints[0], self.startPoints[0], \"y\");\r\n\r\n self.distance = distance(self.newPoints[0], self.startPoints[0]);\r\n\r\n // Skip false ontouchmove events (Chrome)\r\n if (self.distance > 0) {\r\n if (self.isSwiping) {\r\n self.onSwipe(e);\r\n } else if (self.isPanning) {\r\n self.onPan();\r\n } else if (self.isZooming) {\r\n self.onZoom();\r\n }\r\n }\r\n };\r\n\r\n Guestures.prototype.onSwipe = function (e) {\r\n var self = this,\r\n instance = self.instance,\r\n swiping = self.isSwiping,\r\n left = self.sliderStartPos.left || 0,\r\n angle;\r\n\r\n // If direction is not yet determined\r\n if (swiping === true) {\r\n // We need at least 10px distance to correctly calculate an angle\r\n if (Math.abs(self.distance) > 10) {\r\n self.canTap = false;\r\n\r\n if (instance.group.length < 2 && self.opts.vertical) {\r\n self.isSwiping = \"y\";\r\n } else if (instance.isDragging || self.opts.vertical === false || (self.opts.vertical === \"auto\" && $(window).width() > 800)) {\r\n self.isSwiping = \"x\";\r\n } else {\r\n angle = Math.abs((Math.atan2(self.distanceY, self.distanceX) * 180) / Math.PI);\r\n\r\n self.isSwiping = angle > 45 && angle < 135 ? \"y\" : \"x\";\r\n }\r\n\r\n if (self.isSwiping === \"y\" && $.fancybox.isMobile && self.isScrollable) {\r\n self.isScrolling = true;\r\n\r\n return;\r\n }\r\n\r\n instance.isDragging = self.isSwiping;\r\n\r\n // Reset points to avoid jumping, because we dropped first swipes to calculate the angle\r\n self.startPoints = self.newPoints;\r\n\r\n $.each(instance.slides, function (index, slide) {\r\n var slidePos, stagePos;\r\n\r\n $.fancybox.stop(slide.$slide);\r\n\r\n slidePos = $.fancybox.getTranslate(slide.$slide);\r\n stagePos = $.fancybox.getTranslate(instance.$refs.stage);\r\n\r\n slide.$slide\r\n .css({\r\n transform: \"\",\r\n opacity: \"\",\r\n \"transition-duration\": \"\"\r\n })\r\n .removeClass(\"fancybox-animated\")\r\n .removeClass(function (index, className) {\r\n return (className.match(/(^|\\s)fancybox-fx-\\S+/g) || []).join(\" \");\r\n });\r\n\r\n if (slide.pos === instance.current.pos) {\r\n self.sliderStartPos.top = slidePos.top - stagePos.top;\r\n self.sliderStartPos.left = slidePos.left - stagePos.left;\r\n }\r\n\r\n $.fancybox.setTranslate(slide.$slide, {\r\n top: slidePos.top - stagePos.top,\r\n left: slidePos.left - stagePos.left\r\n });\r\n });\r\n\r\n // Stop slideshow\r\n if (instance.SlideShow && instance.SlideShow.isActive) {\r\n instance.SlideShow.stop();\r\n }\r\n }\r\n\r\n return;\r\n }\r\n\r\n // Sticky edges\r\n if (swiping == \"x\") {\r\n if (\r\n self.distanceX > 0 &&\r\n (self.instance.group.length < 2 || (self.instance.current.index === 0 && !self.instance.current.opts.loop))\r\n ) {\r\n left = left + Math.pow(self.distanceX, 0.8);\r\n } else if (\r\n self.distanceX < 0 &&\r\n (self.instance.group.length < 2 ||\r\n (self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop))\r\n ) {\r\n left = left - Math.pow(-self.distanceX, 0.8);\r\n } else {\r\n left = left + self.distanceX;\r\n }\r\n }\r\n\r\n self.sliderLastPos = {\r\n top: swiping == \"x\" ? 0 : self.sliderStartPos.top + self.distanceY,\r\n left: left\r\n };\r\n\r\n if (self.requestId) {\r\n cancelAFrame(self.requestId);\r\n\r\n self.requestId = null;\r\n }\r\n\r\n self.requestId = requestAFrame(function () {\r\n if (self.sliderLastPos) {\r\n $.each(self.instance.slides, function (index, slide) {\r\n var pos = slide.pos - self.instance.currPos;\r\n\r\n $.fancybox.setTranslate(slide.$slide, {\r\n top: self.sliderLastPos.top,\r\n left: self.sliderLastPos.left + pos * self.canvasWidth + pos * slide.opts.gutter\r\n });\r\n });\r\n\r\n self.$container.addClass(\"fancybox-is-sliding\");\r\n }\r\n });\r\n };\r\n\r\n Guestures.prototype.onPan = function () {\r\n var self = this;\r\n\r\n // Prevent accidental movement (sometimes, when tapping casually, finger can move a bit)\r\n if (distance(self.newPoints[0], self.realPoints[0]) < ($.fancybox.isMobile ? 10 : 5)) {\r\n self.startPoints = self.newPoints;\r\n return;\r\n }\r\n\r\n self.canTap = false;\r\n\r\n self.contentLastPos = self.limitMovement();\r\n\r\n if (self.requestId) {\r\n cancelAFrame(self.requestId);\r\n }\r\n\r\n self.requestId = requestAFrame(function () {\r\n $.fancybox.setTranslate(self.$content, self.contentLastPos);\r\n });\r\n };\r\n\r\n // Make panning sticky to the edges\r\n Guestures.prototype.limitMovement = function () {\r\n var self = this;\r\n\r\n var canvasWidth = self.canvasWidth;\r\n var canvasHeight = self.canvasHeight;\r\n\r\n var distanceX = self.distanceX;\r\n var distanceY = self.distanceY;\r\n\r\n var contentStartPos = self.contentStartPos;\r\n\r\n var currentOffsetX = contentStartPos.left;\r\n var currentOffsetY = contentStartPos.top;\r\n\r\n var currentWidth = contentStartPos.width;\r\n var currentHeight = contentStartPos.height;\r\n\r\n var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY, newOffsetX, newOffsetY;\r\n\r\n if (currentWidth > canvasWidth) {\r\n newOffsetX = currentOffsetX + distanceX;\r\n } else {\r\n newOffsetX = currentOffsetX;\r\n }\r\n\r\n newOffsetY = currentOffsetY + distanceY;\r\n\r\n // Slow down proportionally to traveled distance\r\n minTranslateX = Math.max(0, canvasWidth * 0.5 - currentWidth * 0.5);\r\n minTranslateY = Math.max(0, canvasHeight * 0.5 - currentHeight * 0.5);\r\n\r\n maxTranslateX = Math.min(canvasWidth - currentWidth, canvasWidth * 0.5 - currentWidth * 0.5);\r\n maxTranslateY = Math.min(canvasHeight - currentHeight, canvasHeight * 0.5 - currentHeight * 0.5);\r\n\r\n // ->\r\n if (distanceX > 0 && newOffsetX > minTranslateX) {\r\n newOffsetX = minTranslateX - 1 + Math.pow(-minTranslateX + currentOffsetX + distanceX, 0.8) || 0;\r\n }\r\n\r\n // <-\r\n if (distanceX < 0 && newOffsetX < maxTranslateX) {\r\n newOffsetX = maxTranslateX + 1 - Math.pow(maxTranslateX - currentOffsetX - distanceX, 0.8) || 0;\r\n }\r\n\r\n // \\/\r\n if (distanceY > 0 && newOffsetY > minTranslateY) {\r\n newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8) || 0;\r\n }\r\n\r\n // /\\\r\n if (distanceY < 0 && newOffsetY < maxTranslateY) {\r\n newOffsetY = maxTranslateY + 1 - Math.pow(maxTranslateY - currentOffsetY - distanceY, 0.8) || 0;\r\n }\r\n\r\n return {\r\n top: newOffsetY,\r\n left: newOffsetX\r\n };\r\n };\r\n\r\n Guestures.prototype.limitPosition = function (newOffsetX, newOffsetY, newWidth, newHeight) {\r\n var self = this;\r\n\r\n var canvasWidth = self.canvasWidth;\r\n var canvasHeight = self.canvasHeight;\r\n\r\n if (newWidth > canvasWidth) {\r\n newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;\r\n newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;\r\n } else {\r\n // Center horizontally\r\n newOffsetX = Math.max(0, canvasWidth / 2 - newWidth / 2);\r\n }\r\n\r\n if (newHeight > canvasHeight) {\r\n newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;\r\n newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;\r\n } else {\r\n // Center vertically\r\n newOffsetY = Math.max(0, canvasHeight / 2 - newHeight / 2);\r\n }\r\n\r\n return {\r\n top: newOffsetY,\r\n left: newOffsetX\r\n };\r\n };\r\n\r\n Guestures.prototype.onZoom = function () {\r\n var self = this;\r\n\r\n // Calculate current distance between points to get pinch ratio and new width and height\r\n var contentStartPos = self.contentStartPos;\r\n\r\n var currentWidth = contentStartPos.width;\r\n var currentHeight = contentStartPos.height;\r\n\r\n var currentOffsetX = contentStartPos.left;\r\n var currentOffsetY = contentStartPos.top;\r\n\r\n var endDistanceBetweenFingers = distance(self.newPoints[0], self.newPoints[1]);\r\n\r\n var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;\r\n\r\n var newWidth = Math.floor(currentWidth * pinchRatio);\r\n var newHeight = Math.floor(currentHeight * pinchRatio);\r\n\r\n // This is the translation due to pinch-zooming\r\n var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX;\r\n var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;\r\n\r\n // Point between the two touches\r\n var centerPointEndX = (self.newPoints[0].x + self.newPoints[1].x) / 2 - $(window).scrollLeft();\r\n var centerPointEndY = (self.newPoints[0].y + self.newPoints[1].y) / 2 - $(window).scrollTop();\r\n\r\n // And this is the translation due to translation of the centerpoint\r\n // between the two fingers\r\n var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;\r\n var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;\r\n\r\n // The new offset is the old/current one plus the total translation\r\n var newOffsetX = currentOffsetX + (translateFromZoomingX + translateFromTranslatingX);\r\n var newOffsetY = currentOffsetY + (translateFromZoomingY + translateFromTranslatingY);\r\n\r\n var newPos = {\r\n top: newOffsetY,\r\n left: newOffsetX,\r\n scaleX: pinchRatio,\r\n scaleY: pinchRatio\r\n };\r\n\r\n self.canTap = false;\r\n\r\n self.newWidth = newWidth;\r\n self.newHeight = newHeight;\r\n\r\n self.contentLastPos = newPos;\r\n\r\n if (self.requestId) {\r\n cancelAFrame(self.requestId);\r\n }\r\n\r\n self.requestId = requestAFrame(function () {\r\n $.fancybox.setTranslate(self.$content, self.contentLastPos);\r\n });\r\n };\r\n\r\n Guestures.prototype.ontouchend = function (e) {\r\n var self = this;\r\n\r\n var swiping = self.isSwiping;\r\n var panning = self.isPanning;\r\n var zooming = self.isZooming;\r\n var scrolling = self.isScrolling;\r\n\r\n self.endPoints = getPointerXY(e);\r\n self.dMs = Math.max(new Date().getTime() - self.startTime, 1);\r\n\r\n self.$container.removeClass(\"fancybox-is-grabbing\");\r\n\r\n $(document).off(\".fb.touch\");\r\n\r\n document.removeEventListener(\"scroll\", self.onscroll, true);\r\n\r\n if (self.requestId) {\r\n cancelAFrame(self.requestId);\r\n\r\n self.requestId = null;\r\n }\r\n\r\n self.isSwiping = false;\r\n self.isPanning = false;\r\n self.isZooming = false;\r\n self.isScrolling = false;\r\n\r\n self.instance.isDragging = false;\r\n\r\n if (self.canTap) {\r\n return self.onTap(e);\r\n }\r\n\r\n self.speed = 100;\r\n\r\n // Speed in px/ms\r\n self.velocityX = (self.distanceX / self.dMs) * 0.5;\r\n self.velocityY = (self.distanceY / self.dMs) * 0.5;\r\n\r\n if (panning) {\r\n self.endPanning();\r\n } else if (zooming) {\r\n self.endZooming();\r\n } else {\r\n self.endSwiping(swiping, scrolling);\r\n }\r\n\r\n return;\r\n };\r\n\r\n Guestures.prototype.endSwiping = function (swiping, scrolling) {\r\n var self = this,\r\n ret = false,\r\n len = self.instance.group.length,\r\n distanceX = Math.abs(self.distanceX),\r\n canAdvance = swiping == \"x\" && len > 1 && ((self.dMs > 130 && distanceX > 10) || distanceX > 50),\r\n speedX = 300;\r\n\r\n self.sliderLastPos = null;\r\n\r\n // Close if swiped vertically / navigate if horizontally\r\n if (swiping == \"y\" && !scrolling && Math.abs(self.distanceY) > 50) {\r\n // Continue vertical movement\r\n $.fancybox.animate(\r\n self.instance.current.$slide, {\r\n top: self.sliderStartPos.top + self.distanceY + self.velocityY * 150,\r\n opacity: 0\r\n },\r\n 200\r\n );\r\n ret = self.instance.close(true, 250);\r\n } else if (canAdvance && self.distanceX > 0) {\r\n ret = self.instance.previous(speedX);\r\n } else if (canAdvance && self.distanceX < 0) {\r\n ret = self.instance.next(speedX);\r\n }\r\n\r\n if (ret === false && (swiping == \"x\" || swiping == \"y\")) {\r\n self.instance.centerSlide(200);\r\n }\r\n\r\n self.$container.removeClass(\"fancybox-is-sliding\");\r\n };\r\n\r\n // Limit panning from edges\r\n // ========================\r\n Guestures.prototype.endPanning = function () {\r\n var self = this,\r\n newOffsetX,\r\n newOffsetY,\r\n newPos;\r\n\r\n if (!self.contentLastPos) {\r\n return;\r\n }\r\n\r\n if (self.opts.momentum === false || self.dMs > 350) {\r\n newOffsetX = self.contentLastPos.left;\r\n newOffsetY = self.contentLastPos.top;\r\n } else {\r\n // Continue movement\r\n newOffsetX = self.contentLastPos.left + self.velocityX * 500;\r\n newOffsetY = self.contentLastPos.top + self.velocityY * 500;\r\n }\r\n\r\n newPos = self.limitPosition(newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height);\r\n\r\n newPos.width = self.contentStartPos.width;\r\n newPos.height = self.contentStartPos.height;\r\n\r\n $.fancybox.animate(self.$content, newPos, 366);\r\n };\r\n\r\n Guestures.prototype.endZooming = function () {\r\n var self = this;\r\n\r\n var current = self.instance.current;\r\n\r\n var newOffsetX, newOffsetY, newPos, reset;\r\n\r\n var newWidth = self.newWidth;\r\n var newHeight = self.newHeight;\r\n\r\n if (!self.contentLastPos) {\r\n return;\r\n }\r\n\r\n newOffsetX = self.contentLastPos.left;\r\n newOffsetY = self.contentLastPos.top;\r\n\r\n reset = {\r\n top: newOffsetY,\r\n left: newOffsetX,\r\n width: newWidth,\r\n height: newHeight,\r\n scaleX: 1,\r\n scaleY: 1\r\n };\r\n\r\n // Reset scalex/scaleY values; this helps for perfomance and does not break animation\r\n $.fancybox.setTranslate(self.$content, reset);\r\n\r\n if (newWidth < self.canvasWidth && newHeight < self.canvasHeight) {\r\n self.instance.scaleToFit(150);\r\n } else if (newWidth > current.width || newHeight > current.height) {\r\n self.instance.scaleToActual(self.centerPointStartX, self.centerPointStartY, 150);\r\n } else {\r\n newPos = self.limitPosition(newOffsetX, newOffsetY, newWidth, newHeight);\r\n\r\n $.fancybox.animate(self.$content, newPos, 150);\r\n }\r\n };\r\n\r\n Guestures.prototype.onTap = function (e) {\r\n var self = this;\r\n var $target = $(e.target);\r\n\r\n var instance = self.instance;\r\n var current = instance.current;\r\n\r\n var endPoints = (e && getPointerXY(e)) || self.startPoints;\r\n\r\n var tapX = endPoints[0] ? endPoints[0].x - $(window).scrollLeft() - self.stagePos.left : 0;\r\n var tapY = endPoints[0] ? endPoints[0].y - $(window).scrollTop() - self.stagePos.top : 0;\r\n\r\n var where;\r\n\r\n var process = function (prefix) {\r\n var action = current.opts[prefix];\r\n\r\n if ($.isFunction(action)) {\r\n action = action.apply(instance, [current, e]);\r\n }\r\n\r\n if (!action) {\r\n return;\r\n }\r\n\r\n switch (action) {\r\n case \"close\":\r\n instance.close(self.startEvent);\r\n\r\n break;\r\n\r\n case \"toggleControls\":\r\n instance.toggleControls();\r\n\r\n break;\r\n\r\n case \"next\":\r\n instance.next();\r\n\r\n break;\r\n\r\n case \"nextOrClose\":\r\n if (instance.group.length > 1) {\r\n instance.next();\r\n } else {\r\n instance.close(self.startEvent);\r\n }\r\n\r\n break;\r\n\r\n case \"zoom\":\r\n if (current.type == \"image\" && (current.isLoaded || current.$ghost)) {\r\n if (instance.canPan()) {\r\n instance.scaleToFit();\r\n } else if (instance.isScaledDown()) {\r\n instance.scaleToActual(tapX, tapY);\r\n } else if (instance.group.length < 2) {\r\n instance.close(self.startEvent);\r\n }\r\n }\r\n\r\n break;\r\n }\r\n };\r\n\r\n // Ignore right click\r\n if (e.originalEvent && e.originalEvent.button == 2) {\r\n return;\r\n }\r\n\r\n // Skip if clicked on the scrollbar\r\n if (!$target.is(\"img\") && tapX > $target[0].clientWidth + $target.offset().left) {\r\n return;\r\n }\r\n\r\n // Check where is clicked\r\n if ($target.is(\".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container\")) {\r\n where = \"Outside\";\r\n } else if ($target.is(\".fancybox-slide\")) {\r\n where = \"Slide\";\r\n } else if (\r\n instance.current.$content &&\r\n instance.current.$content\r\n .find($target)\r\n .addBack()\r\n .filter($target).length\r\n ) {\r\n where = \"Content\";\r\n } else {\r\n return;\r\n }\r\n\r\n // Check if this is a double tap\r\n if (self.tapped) {\r\n // Stop previously created single tap\r\n clearTimeout(self.tapped);\r\n self.tapped = null;\r\n\r\n // Skip if distance between taps is too big\r\n if (Math.abs(tapX - self.tapX) > 50 || Math.abs(tapY - self.tapY) > 50) {\r\n return this;\r\n }\r\n\r\n // OK, now we assume that this is a double-tap\r\n process(\"dblclick\" + where);\r\n } else {\r\n // Single tap will be processed if user has not clicked second time within 300ms\r\n // or there is no need to wait for double-tap\r\n self.tapX = tapX;\r\n self.tapY = tapY;\r\n\r\n if (current.opts[\"dblclick\" + where] && current.opts[\"dblclick\" + where] !== current.opts[\"click\" + where]) {\r\n self.tapped = setTimeout(function () {\r\n self.tapped = null;\r\n\r\n if (!instance.isAnimating) {\r\n process(\"click\" + where);\r\n }\r\n }, 500);\r\n } else {\r\n process(\"click\" + where);\r\n }\r\n }\r\n\r\n return this;\r\n };\r\n\r\n $(document)\r\n .on(\"onActivate.fb\", function (e, instance) {\r\n if (instance && !instance.Guestures) {\r\n instance.Guestures = new Guestures(instance);\r\n }\r\n })\r\n .on(\"beforeClose.fb\", function (e, instance) {\r\n if (instance && instance.Guestures) {\r\n instance.Guestures.destroy();\r\n }\r\n });\r\n})(window, document, jQuery);\n// ==========================================================================\r\n//\r\n// SlideShow\r\n// Enables slideshow functionality\r\n//\r\n// Example of usage:\r\n// $.fancybox.getInstance().SlideShow.start()\r\n//\r\n// ==========================================================================\r\n(function (document, $) {\r\n \"use strict\";\r\n\r\n $.extend(true, $.fancybox.defaults, {\r\n btnTpl: {\r\n slideShow: '\"\r\n },\r\n slideShow: {\r\n autoStart: false,\r\n speed: 3000,\r\n progress: true\r\n }\r\n });\r\n\r\n var SlideShow = function (instance) {\r\n this.instance = instance;\r\n this.init();\r\n };\r\n\r\n $.extend(SlideShow.prototype, {\r\n timer: null,\r\n isActive: false,\r\n $button: null,\r\n\r\n init: function () {\r\n var self = this,\r\n instance = self.instance,\r\n opts = instance.group[instance.currIndex].opts.slideShow;\r\n\r\n self.$button = instance.$refs.toolbar.find(\"[data-fancybox-play]\").on(\"click\", function () {\r\n self.toggle();\r\n });\r\n\r\n if (instance.group.length < 2 || !opts) {\r\n self.$button.hide();\r\n } else if (opts.progress) {\r\n self.$progress = $('
').appendTo(instance.$refs.inner);\r\n }\r\n },\r\n\r\n set: function (force) {\r\n var self = this,\r\n instance = self.instance,\r\n current = instance.current;\r\n\r\n // Check if reached last element\r\n if (current && (force === true || current.opts.loop || instance.currIndex < instance.group.length - 1)) {\r\n if (self.isActive && current.contentType !== \"video\") {\r\n if (self.$progress) {\r\n $.fancybox.animate(self.$progress.show(), {\r\n scaleX: 1\r\n }, current.opts.slideShow.speed);\r\n }\r\n\r\n self.timer = setTimeout(function () {\r\n if (!instance.current.opts.loop && instance.current.index == instance.group.length - 1) {\r\n instance.jumpTo(0);\r\n } else {\r\n instance.next();\r\n }\r\n }, current.opts.slideShow.speed);\r\n }\r\n } else {\r\n self.stop();\r\n instance.idleSecondsCounter = 0;\r\n instance.showControls();\r\n }\r\n },\r\n\r\n clear: function () {\r\n var self = this;\r\n\r\n clearTimeout(self.timer);\r\n\r\n self.timer = null;\r\n\r\n if (self.$progress) {\r\n self.$progress.removeAttr(\"style\").hide();\r\n }\r\n },\r\n\r\n start: function () {\r\n var self = this,\r\n current = self.instance.current;\r\n\r\n if (current) {\r\n self.$button\r\n .attr(\"title\", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_STOP)\r\n .removeClass(\"fancybox-button--play\")\r\n .addClass(\"fancybox-button--pause\");\r\n\r\n self.isActive = true;\r\n\r\n if (current.isComplete) {\r\n self.set(true);\r\n }\r\n\r\n self.instance.trigger(\"onSlideShowChange\", true);\r\n }\r\n },\r\n\r\n stop: function () {\r\n var self = this,\r\n current = self.instance.current;\r\n\r\n self.clear();\r\n\r\n self.$button\r\n .attr(\"title\", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_START)\r\n .removeClass(\"fancybox-button--pause\")\r\n .addClass(\"fancybox-button--play\");\r\n\r\n self.isActive = false;\r\n\r\n self.instance.trigger(\"onSlideShowChange\", false);\r\n\r\n if (self.$progress) {\r\n self.$progress.removeAttr(\"style\").hide();\r\n }\r\n },\r\n\r\n toggle: function () {\r\n var self = this;\r\n\r\n if (self.isActive) {\r\n self.stop();\r\n } else {\r\n self.start();\r\n }\r\n }\r\n });\r\n\r\n $(document).on({\r\n \"onInit.fb\": function (e, instance) {\r\n if (instance && !instance.SlideShow) {\r\n instance.SlideShow = new SlideShow(instance);\r\n }\r\n },\r\n\r\n \"beforeShow.fb\": function (e, instance, current, firstRun) {\r\n var SlideShow = instance && instance.SlideShow;\r\n\r\n if (firstRun) {\r\n if (SlideShow && current.opts.slideShow.autoStart) {\r\n SlideShow.start();\r\n }\r\n } else if (SlideShow && SlideShow.isActive) {\r\n SlideShow.clear();\r\n }\r\n },\r\n\r\n \"afterShow.fb\": function (e, instance, current) {\r\n var SlideShow = instance && instance.SlideShow;\r\n\r\n if (SlideShow && SlideShow.isActive) {\r\n SlideShow.set();\r\n }\r\n },\r\n\r\n \"afterKeydown.fb\": function (e, instance, current, keypress, keycode) {\r\n var SlideShow = instance && instance.SlideShow;\r\n\r\n // \"P\" or Spacebar\r\n if (SlideShow && current.opts.slideShow && (keycode === 80 || keycode === 32) && !$(document.activeElement).is(\"button,a,input\")) {\r\n keypress.preventDefault();\r\n\r\n SlideShow.toggle();\r\n }\r\n },\r\n\r\n \"beforeClose.fb onDeactivate.fb\": function (e, instance) {\r\n var SlideShow = instance && instance.SlideShow;\r\n\r\n if (SlideShow) {\r\n SlideShow.stop();\r\n }\r\n }\r\n });\r\n\r\n // Page Visibility API to pause slideshow when window is not active\r\n $(document).on(\"visibilitychange\", function () {\r\n var instance = $.fancybox.getInstance(),\r\n SlideShow = instance && instance.SlideShow;\r\n\r\n if (SlideShow && SlideShow.isActive) {\r\n if (document.hidden) {\r\n SlideShow.clear();\r\n } else {\r\n SlideShow.set();\r\n }\r\n }\r\n });\r\n})(document, jQuery);\n// ==========================================================================\r\n//\r\n// FullScreen\r\n// Adds fullscreen functionality\r\n//\r\n// ==========================================================================\r\n(function (document, $) {\r\n \"use strict\";\r\n\r\n // Collection of methods supported by user browser\r\n var fn = (function () {\r\n var fnMap = [\r\n [\"requestFullscreen\", \"exitFullscreen\", \"fullscreenElement\", \"fullscreenEnabled\", \"fullscreenchange\", \"fullscreenerror\"],\r\n // new WebKit\r\n [\r\n \"webkitRequestFullscreen\",\r\n \"webkitExitFullscreen\",\r\n \"webkitFullscreenElement\",\r\n \"webkitFullscreenEnabled\",\r\n \"webkitfullscreenchange\",\r\n \"webkitfullscreenerror\"\r\n ],\r\n // old WebKit (Safari 5.1)\r\n [\r\n \"webkitRequestFullScreen\",\r\n \"webkitCancelFullScreen\",\r\n \"webkitCurrentFullScreenElement\",\r\n \"webkitCancelFullScreen\",\r\n \"webkitfullscreenchange\",\r\n \"webkitfullscreenerror\"\r\n ],\r\n [\r\n \"mozRequestFullScreen\",\r\n \"mozCancelFullScreen\",\r\n \"mozFullScreenElement\",\r\n \"mozFullScreenEnabled\",\r\n \"mozfullscreenchange\",\r\n \"mozfullscreenerror\"\r\n ],\r\n [\"msRequestFullscreen\", \"msExitFullscreen\", \"msFullscreenElement\", \"msFullscreenEnabled\", \"MSFullscreenChange\", \"MSFullscreenError\"]\r\n ];\r\n\r\n var ret = {};\r\n\r\n for (var i = 0; i < fnMap.length; i++) {\r\n var val = fnMap[i];\r\n\r\n if (val && val[1] in document) {\r\n for (var j = 0; j < val.length; j++) {\r\n ret[fnMap[0][j]] = val[j];\r\n }\r\n\r\n return ret;\r\n }\r\n }\r\n\r\n return false;\r\n })();\r\n\r\n if (fn) {\r\n var FullScreen = {\r\n request: function (elem) {\r\n elem = elem || document.documentElement;\r\n\r\n elem[fn.requestFullscreen](elem.ALLOW_KEYBOARD_INPUT);\r\n },\r\n exit: function () {\r\n document[fn.exitFullscreen]();\r\n },\r\n toggle: function (elem) {\r\n elem = elem || document.documentElement;\r\n\r\n if (this.isFullscreen()) {\r\n this.exit();\r\n } else {\r\n this.request(elem);\r\n }\r\n },\r\n isFullscreen: function () {\r\n return Boolean(document[fn.fullscreenElement]);\r\n },\r\n enabled: function () {\r\n return Boolean(document[fn.fullscreenEnabled]);\r\n }\r\n };\r\n\r\n $.extend(true, $.fancybox.defaults, {\r\n btnTpl: {\r\n fullScreen: '\"\r\n },\r\n fullScreen: {\r\n autoStart: false\r\n }\r\n });\r\n\r\n $(document).on(fn.fullscreenchange, function () {\r\n var isFullscreen = FullScreen.isFullscreen(),\r\n instance = $.fancybox.getInstance();\r\n\r\n if (instance) {\r\n // If image is zooming, then force to stop and reposition properly\r\n if (instance.current && instance.current.type === \"image\" && instance.isAnimating) {\r\n instance.isAnimating = false;\r\n\r\n instance.update(true, true, 0);\r\n\r\n if (!instance.isComplete) {\r\n instance.complete();\r\n }\r\n }\r\n\r\n instance.trigger(\"onFullscreenChange\", isFullscreen);\r\n\r\n instance.$refs.container.toggleClass(\"fancybox-is-fullscreen\", isFullscreen);\r\n\r\n instance.$refs.toolbar\r\n .find(\"[data-fancybox-fullscreen]\")\r\n .toggleClass(\"fancybox-button--fsenter\", !isFullscreen)\r\n .toggleClass(\"fancybox-button--fsexit\", isFullscreen);\r\n }\r\n });\r\n }\r\n\r\n $(document).on({\r\n \"onInit.fb\": function (e, instance) {\r\n var $container;\r\n\r\n if (!fn) {\r\n instance.$refs.toolbar.find(\"[data-fancybox-fullscreen]\").remove();\r\n\r\n return;\r\n }\r\n\r\n if (instance && instance.group[instance.currIndex].opts.fullScreen) {\r\n $container = instance.$refs.container;\r\n\r\n $container.on(\"click.fb-fullscreen\", \"[data-fancybox-fullscreen]\", function (e) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n\r\n FullScreen.toggle();\r\n });\r\n\r\n if (instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true) {\r\n FullScreen.request();\r\n }\r\n\r\n // Expose API\r\n instance.FullScreen = FullScreen;\r\n } else if (instance) {\r\n instance.$refs.toolbar.find(\"[data-fancybox-fullscreen]\").hide();\r\n }\r\n },\r\n\r\n \"afterKeydown.fb\": function (e, instance, current, keypress, keycode) {\r\n // \"F\"\r\n if (instance && instance.FullScreen && keycode === 70) {\r\n keypress.preventDefault();\r\n\r\n instance.FullScreen.toggle();\r\n }\r\n },\r\n\r\n \"beforeClose.fb\": function (e, instance) {\r\n if (instance && instance.FullScreen && instance.$refs.container.hasClass(\"fancybox-is-fullscreen\")) {\r\n FullScreen.exit();\r\n }\r\n }\r\n });\r\n})(document, jQuery);\n// ==========================================================================\r\n//\r\n// Thumbs\r\n// Displays thumbnails in a grid\r\n//\r\n// ==========================================================================\r\n(function (document, $) {\r\n \"use strict\";\r\n\r\n var CLASS = \"fancybox-thumbs\",\r\n CLASS_ACTIVE = CLASS + \"-active\";\r\n\r\n // Make sure there are default values\r\n $.fancybox.defaults = $.extend(\r\n true, {\r\n btnTpl: {\r\n thumbs: '\"\r\n },\r\n thumbs: {\r\n autoStart: false, // Display thumbnails on opening\r\n hideOnClose: true, // Hide thumbnail grid when closing animation starts\r\n parentEl: \".fancybox-container\", // Container is injected into this element\r\n axis: \"y\" // Vertical (y) or horizontal (x) scrolling\r\n }\r\n },\r\n $.fancybox.defaults\r\n );\r\n\r\n var FancyThumbs = function (instance) {\r\n this.init(instance);\r\n };\r\n\r\n $.extend(FancyThumbs.prototype, {\r\n $button: null,\r\n $grid: null,\r\n $list: null,\r\n isVisible: false,\r\n isActive: false,\r\n\r\n init: function (instance) {\r\n var self = this,\r\n group = instance.group,\r\n enabled = 0;\r\n\r\n self.instance = instance;\r\n self.opts = group[instance.currIndex].opts.thumbs;\r\n\r\n instance.Thumbs = self;\r\n\r\n self.$button = instance.$refs.toolbar.find(\"[data-fancybox-thumbs]\");\r\n\r\n // Enable thumbs if at least two group items have thumbnails\r\n for (var i = 0, len = group.length; i < len; i++) {\r\n if (group[i].thumb) {\r\n enabled++;\r\n }\r\n\r\n if (enabled > 1) {\r\n break;\r\n }\r\n }\r\n\r\n if (enabled > 1 && !!self.opts) {\r\n self.$button.removeAttr(\"style\").on(\"click\", function () {\r\n self.toggle();\r\n });\r\n\r\n self.isActive = true;\r\n } else {\r\n self.$button.hide();\r\n }\r\n },\r\n\r\n create: function () {\r\n var self = this,\r\n instance = self.instance,\r\n parentEl = self.opts.parentEl,\r\n list = [],\r\n src;\r\n\r\n if (!self.$grid) {\r\n // Create main element\r\n self.$grid = $('
').appendTo(\r\n instance.$refs.container\r\n .find(parentEl)\r\n .addBack()\r\n .filter(parentEl)\r\n );\r\n\r\n // Add \"click\" event that performs gallery navigation\r\n self.$grid.on(\"click\", \"a\", function () {\r\n instance.jumpTo($(this).attr(\"data-index\"));\r\n });\r\n }\r\n\r\n // Build the list\r\n if (!self.$list) {\r\n self.$list = $('
').appendTo(self.$grid);\r\n }\r\n\r\n $.each(instance.group, function (i, item) {\r\n src = item.thumb;\r\n\r\n if (!src && item.type === \"image\") {\r\n src = item.src;\r\n }\r\n\r\n list.push(\r\n '\"\r\n );\r\n });\r\n\r\n self.$list[0].innerHTML = list.join(\"\");\r\n\r\n if (self.opts.axis === \"x\") {\r\n // Set fixed width for list element to enable horizontal scrolling\r\n self.$list.width(\r\n parseInt(self.$grid.css(\"padding-right\"), 10) +\r\n instance.group.length *\r\n self.$list\r\n .children()\r\n .eq(0)\r\n .outerWidth(true)\r\n );\r\n }\r\n },\r\n\r\n focus: function (duration) {\r\n var self = this,\r\n $list = self.$list,\r\n $grid = self.$grid,\r\n thumb,\r\n thumbPos;\r\n\r\n if (!self.instance.current) {\r\n return;\r\n }\r\n\r\n thumb = $list\r\n .children()\r\n .removeClass(CLASS_ACTIVE)\r\n .filter('[data-index=\"' + self.instance.current.index + '\"]')\r\n .addClass(CLASS_ACTIVE);\r\n\r\n thumbPos = thumb.position();\r\n\r\n // Check if need to scroll to make current thumb visible\r\n if (self.opts.axis === \"y\" && (thumbPos.top < 0 || thumbPos.top > $list.height() - thumb.outerHeight())) {\r\n $list.stop().animate({\r\n scrollTop: $list.scrollTop() + thumbPos.top\r\n },\r\n duration\r\n );\r\n } else if (\r\n self.opts.axis === \"x\" &&\r\n (thumbPos.left < $grid.scrollLeft() || thumbPos.left > $grid.scrollLeft() + ($grid.width() - thumb.outerWidth()))\r\n ) {\r\n $list\r\n .parent()\r\n .stop()\r\n .animate({\r\n scrollLeft: thumbPos.left\r\n },\r\n duration\r\n );\r\n }\r\n },\r\n\r\n update: function () {\r\n var that = this;\r\n that.instance.$refs.container.toggleClass(\"fancybox-show-thumbs\", this.isVisible);\r\n\r\n if (that.isVisible) {\r\n if (!that.$grid) {\r\n that.create();\r\n }\r\n\r\n that.instance.trigger(\"onThumbsShow\");\r\n\r\n that.focus(0);\r\n } else if (that.$grid) {\r\n that.instance.trigger(\"onThumbsHide\");\r\n }\r\n\r\n // Update content position\r\n that.instance.update();\r\n },\r\n\r\n hide: function () {\r\n this.isVisible = false;\r\n this.update();\r\n },\r\n\r\n show: function () {\r\n this.isVisible = true;\r\n this.update();\r\n },\r\n\r\n toggle: function () {\r\n this.isVisible = !this.isVisible;\r\n this.update();\r\n }\r\n });\r\n\r\n $(document).on({\r\n \"onInit.fb\": function (e, instance) {\r\n var Thumbs;\r\n\r\n if (instance && !instance.Thumbs) {\r\n Thumbs = new FancyThumbs(instance);\r\n\r\n if (Thumbs.isActive && Thumbs.opts.autoStart === true) {\r\n Thumbs.show();\r\n }\r\n }\r\n },\r\n\r\n \"beforeShow.fb\": function (e, instance, item, firstRun) {\r\n var Thumbs = instance && instance.Thumbs;\r\n\r\n if (Thumbs && Thumbs.isVisible) {\r\n Thumbs.focus(firstRun ? 0 : 250);\r\n }\r\n },\r\n\r\n \"afterKeydown.fb\": function (e, instance, current, keypress, keycode) {\r\n var Thumbs = instance && instance.Thumbs;\r\n\r\n // \"G\"\r\n if (Thumbs && Thumbs.isActive && keycode === 71) {\r\n keypress.preventDefault();\r\n\r\n Thumbs.toggle();\r\n }\r\n },\r\n\r\n \"beforeClose.fb\": function (e, instance) {\r\n var Thumbs = instance && instance.Thumbs;\r\n\r\n if (Thumbs && Thumbs.isVisible && Thumbs.opts.hideOnClose !== false) {\r\n Thumbs.$grid.hide();\r\n }\r\n }\r\n });\r\n})(document, jQuery);\n//// ==========================================================================\r\n//\r\n// Share\r\n// Displays simple form for sharing current url\r\n//\r\n// ==========================================================================\r\n(function (document, $) {\r\n \"use strict\";\r\n\r\n $.extend(true, $.fancybox.defaults, {\r\n btnTpl: {\r\n share: '\"\r\n },\r\n share: {\r\n url: function (instance, item) {\r\n return (\r\n (!instance.currentHash && !(item.type === \"inline\" || item.type === \"html\") ? item.origSrc || item.src : false) || window.location\r\n );\r\n },\r\n tpl: '
' +\r\n \"

{{SHARE}}

\" +\r\n \"

\" +\r\n '' +\r\n '' +\r\n \"Facebook\" +\r\n \"\" +\r\n '' +\r\n '' +\r\n \"Twitter\" +\r\n \"\" +\r\n '' +\r\n '' +\r\n \"Pinterest\" +\r\n \"\" +\r\n \"

\" +\r\n '

' +\r\n \"
\"\r\n }\r\n });\r\n\r\n function escapeHtml(string) {\r\n var entityMap = {\r\n \"&\": \"&\",\r\n \"<\": \"<\",\r\n \">\": \">\",\r\n '\"': \""\",\r\n \"'\": \"'\",\r\n \"/\": \"/\",\r\n \"`\": \"`\",\r\n \"=\": \"=\"\r\n };\r\n\r\n return String(string).replace(/[&<>\"'`=\\/]/g, function (s) {\r\n return entityMap[s];\r\n });\r\n }\r\n\r\n $(document).on(\"click\", \"[data-fancybox-share]\", function () {\r\n var instance = $.fancybox.getInstance(),\r\n current = instance.current || null,\r\n url,\r\n tpl;\r\n\r\n if (!current) {\r\n return;\r\n }\r\n\r\n if ($.type(current.opts.share.url) === \"function\") {\r\n url = current.opts.share.url.apply(current, [instance, current]);\r\n }\r\n\r\n tpl = current.opts.share.tpl\r\n .replace(/\\{\\{media\\}\\}/g, current.type === \"image\" ? encodeURIComponent(current.src) : \"\")\r\n .replace(/\\{\\{url\\}\\}/g, encodeURIComponent(url))\r\n .replace(/\\{\\{url_raw\\}\\}/g, escapeHtml(url))\r\n .replace(/\\{\\{descr\\}\\}/g, instance.$caption ? encodeURIComponent(instance.$caption.text()) : \"\");\r\n\r\n $.fancybox.open({\r\n src: instance.translate(instance, tpl),\r\n type: \"html\",\r\n opts: {\r\n touch: false,\r\n animationEffect: false,\r\n afterLoad: function (shareInstance, shareCurrent) {\r\n // Close self if parent instance is closing\r\n instance.$refs.container.one(\"beforeClose.fb\", function () {\r\n shareInstance.close(null, 0);\r\n });\r\n\r\n // Opening links in a popup window\r\n shareCurrent.$content.find(\".fancybox-share__button\").click(function () {\r\n window.open(this.href, \"Share\", \"width=550, height=450\");\r\n return false;\r\n });\r\n },\r\n mobile: {\r\n autoFocus: false\r\n }\r\n }\r\n });\r\n });\r\n})(document, jQuery);\n// ==========================================================================\r\n//\r\n// Hash\r\n// Enables linking to each modal\r\n//\r\n// ==========================================================================\r\n(function (window, document, $) {\r\n \"use strict\";\r\n\r\n // Simple $.escapeSelector polyfill (for jQuery prior v3)\r\n if (!$.escapeSelector) {\r\n $.escapeSelector = function (sel) {\r\n var rcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\x80-\\uFFFF\\w-]/g;\r\n var fcssescape = function (ch, asCodePoint) {\r\n if (asCodePoint) {\r\n // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\r\n if (ch === \"\\0\") {\r\n return \"\\uFFFD\";\r\n }\r\n\r\n // Control characters and (dependent upon position) numbers get escaped as code points\r\n return ch.slice(0, -1) + \"\\\\\" + ch.charCodeAt(ch.length - 1).toString(16) + \" \";\r\n }\r\n\r\n // Other potentially-special ASCII characters get backslash-escaped\r\n return \"\\\\\" + ch;\r\n };\r\n\r\n return (sel + \"\").replace(rcssescape, fcssescape);\r\n };\r\n }\r\n\r\n // Get info about gallery name and current index from url\r\n function parseUrl() {\r\n var hash = window.location.hash.substr(1),\r\n rez = hash.split(\"-\"),\r\n index = rez.length > 1 && /^\\+?\\d+$/.test(rez[rez.length - 1]) ? parseInt(rez.pop(-1), 10) || 1 : 1,\r\n gallery = rez.join(\"-\");\r\n\r\n return {\r\n hash: hash,\r\n /* Index is starting from 1 */\r\n index: index < 1 ? 1 : index,\r\n gallery: gallery\r\n };\r\n }\r\n\r\n // Trigger click evnt on links to open new fancyBox instance\r\n function triggerFromUrl(url) {\r\n if (url.gallery !== \"\") {\r\n // If we can find element matching 'data-fancybox' atribute,\r\n // then triggering click event should start fancyBox\r\n $(\"[data-fancybox='\" + $.escapeSelector(url.gallery) + \"']\")\r\n .eq(url.index - 1)\r\n .focus()\r\n .trigger(\"click.fb-start\");\r\n }\r\n }\r\n\r\n // Get gallery name from current instance\r\n function getGalleryID(instance) {\r\n var opts, ret;\r\n\r\n if (!instance) {\r\n return false;\r\n }\r\n\r\n opts = instance.current ? instance.current.opts : instance.opts;\r\n ret = opts.hash || (opts.$orig ? opts.$orig.data(\"fancybox\") || opts.$orig.data(\"fancybox-trigger\") : \"\");\r\n\r\n return ret === \"\" ? false : ret;\r\n }\r\n\r\n // Start when DOM becomes ready\r\n $(function () {\r\n // Check if user has disabled this module\r\n if ($.fancybox.defaults.hash === false) {\r\n return;\r\n }\r\n\r\n // Update hash when opening/closing fancyBox\r\n $(document).on({\r\n \"onInit.fb\": function (e, instance) {\r\n var url, gallery;\r\n\r\n if (instance.group[instance.currIndex].opts.hash === false) {\r\n return;\r\n }\r\n\r\n url = parseUrl();\r\n gallery = getGalleryID(instance);\r\n\r\n // Make sure gallery start index matches index from hash\r\n if (gallery && url.gallery && gallery == url.gallery) {\r\n instance.currIndex = url.index - 1;\r\n }\r\n },\r\n\r\n \"beforeShow.fb\": function (e, instance, current, firstRun) {\r\n var gallery;\r\n\r\n if (!current || current.opts.hash === false) {\r\n return;\r\n }\r\n\r\n // Check if need to update window hash\r\n gallery = getGalleryID(instance);\r\n\r\n if (!gallery) {\r\n return;\r\n }\r\n\r\n // Variable containing last hash value set by fancyBox\r\n // It will be used to determine if fancyBox needs to close after hash change is detected\r\n instance.currentHash = gallery + (instance.group.length > 1 ? \"-\" + (current.index + 1) : \"\");\r\n\r\n // If current hash is the same (this instance most likely is opened by hashchange), then do nothing\r\n if (window.location.hash === \"#\" + instance.currentHash) {\r\n return;\r\n }\r\n\r\n if (firstRun && !instance.origHash) {\r\n instance.origHash = window.location.hash;\r\n }\r\n\r\n if (instance.hashTimer) {\r\n clearTimeout(instance.hashTimer);\r\n }\r\n\r\n // Update hash\r\n instance.hashTimer = setTimeout(function () {\r\n if (\"replaceState\" in window.history) {\r\n window.history[firstRun ? \"pushState\" : \"replaceState\"]({},\r\n document.title,\r\n window.location.pathname + window.location.search + \"#\" + instance.currentHash\r\n );\r\n\r\n if (firstRun) {\r\n instance.hasCreatedHistory = true;\r\n }\r\n } else {\r\n window.location.hash = instance.currentHash;\r\n }\r\n\r\n instance.hashTimer = null;\r\n }, 300);\r\n },\r\n\r\n \"beforeClose.fb\": function (e, instance, current) {\r\n if (!current || current.opts.hash === false) {\r\n return;\r\n }\r\n\r\n clearTimeout(instance.hashTimer);\r\n\r\n // Goto previous history entry\r\n if (instance.currentHash && instance.hasCreatedHistory) {\r\n window.history.back();\r\n } else if (instance.currentHash) {\r\n if (\"replaceState\" in window.history) {\r\n window.history.replaceState({}, document.title, window.location.pathname + window.location.search + (instance.origHash || \"\"));\r\n } else {\r\n window.location.hash = instance.origHash;\r\n }\r\n }\r\n\r\n instance.currentHash = null;\r\n }\r\n });\r\n\r\n // Check if need to start/close after url has changed\r\n $(window).on(\"hashchange.fb\", function () {\r\n var url = parseUrl(),\r\n fb = null;\r\n\r\n // Find last fancyBox instance that has \"hash\"\r\n $.each(\r\n $(\".fancybox-container\")\r\n .get()\r\n .reverse(),\r\n function (index, value) {\r\n var tmp = $(value).data(\"FancyBox\");\r\n\r\n if (tmp && tmp.currentHash) {\r\n fb = tmp;\r\n return false;\r\n }\r\n }\r\n );\r\n\r\n if (fb) {\r\n // Now, compare hash values\r\n if (fb.currentHash !== url.gallery + \"-\" + url.index && !(url.index === 1 && fb.currentHash == url.gallery)) {\r\n fb.currentHash = null;\r\n\r\n fb.close();\r\n }\r\n } else if (url.gallery !== \"\") {\r\n triggerFromUrl(url);\r\n }\r\n });\r\n\r\n // Check current hash and trigger click event on matching element to start fancyBox, if needed\r\n setTimeout(function () {\r\n if (!$.fancybox.getInstance()) {\r\n triggerFromUrl(parseUrl());\r\n }\r\n }, 50);\r\n });\r\n})(window, document, jQuery);\n// ==========================================================================\r\n//\r\n// Wheel\r\n// Basic mouse weheel support for gallery navigation\r\n//\r\n// ==========================================================================\r\n(function (document, $) {\r\n \"use strict\";\r\n\r\n var prevTime = new Date().getTime();\r\n\r\n $(document).on({\r\n \"onInit.fb\": function (e, instance, current) {\r\n instance.$refs.stage.on(\"mousewheel DOMMouseScroll wheel MozMousePixelScroll\", function (e) {\r\n var current = instance.current,\r\n currTime = new Date().getTime();\r\n\r\n if (instance.group.length < 2 || current.opts.wheel === false || (current.opts.wheel === \"auto\" && current.type !== \"image\")) {\r\n return;\r\n }\r\n\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n if (current.$slide.hasClass(\"fancybox-animated\")) {\r\n return;\r\n }\r\n\r\n e = e.originalEvent || e;\r\n\r\n if (currTime - prevTime < 250) {\r\n return;\r\n }\r\n\r\n prevTime = currTime;\r\n\r\n instance[(-e.deltaY || -e.deltaX || e.wheelDelta || -e.detail) < 0 ? \"next\" : \"previous\"]();\r\n });\r\n }\r\n });\r\n})(document, jQuery);","/*\n * FancyBox Extension for Flarum\n * Copyright (C) 2019 Eleanor Hawk\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n */\n\nimport { extend } from 'flarum/extend';\nimport CommentPost from 'flarum/components/CommentPost';\nimport ModalManager from 'flarum/components/ModalManager';\nimport fancybox from \"@fancyapps/fancybox\";\n\nfunction categorizeImages(element) {\n const imageWrapperHtml = '
';\n const badgeHtml = `\n `;\n var captionHtml = function (caption) {\n return `\n
\n ` + caption + `\n
\n `;\n };\n\n $(element).find('p, th, td').children('img:not([class]):not([data-nothing-fancy])').each((i, e) => {\n let caption = $(e).attr('title') || '';\n\n if ($(e).parent().contents().length === 1) {\n $(e).addClass('block-image');\n $(e).wrap('' + imageWrapperHtml + '');\n } else {\n $(e).addClass('inline-image');\n $(e).wrap('' + imageWrapperHtml + '');\n }\n\n $(e).parent().append(badgeHtml);\n if (caption !== '') $(e).closest('a').append(captionHtml(caption));\n });\n\n $(element).find('p, th, td').find(`a:not(\n .block-image-link,\n .inline-image-link,\n .block-image-self-link,\n .inline-image-self-link\n ) > img:not([class])`).each((i, e) => {\n let link = $(e).parent();\n\n if (typeof $(e).data('nothing-fancy') !== 'undefined'\n && !(link.hasClass('fancybox--iframe-link') || link.hasClass('fancybox--video-link'))) {\n \treturn true;\n }\n\n let caption = $(e).attr('title') || link.attr('title') || '';\n\n if (link.contents().length === 1\n && link.parent().contents().length === 1) {\n $(e).addClass('block-image');\n if ($(e).attr('src') !== link.attr('href')) {\n link.addClass('block-image-link');\n } else {\n link.addClass('block-image-self-link');\n }\n } else {\n $(e).addClass('inline-image');\n if ($(e).attr('src') !== link.attr('href')) {\n link.addClass('inline-image-link');\n } else {\n link.addClass('inline-image-self-link');\n }\n }\n\n link.append(badgeHtml);\n link.wrapInner(imageWrapperHtml);\n if (caption !== '') link.append(captionHtml(caption));\n });\n}\n\napp.initializers.add('the-turk-fancybox', app => {\n $.fancybox.defaults.toolbar = false;\n $.fancybox.defaults.smallBtn = true;\n $.fancybox.defaults.lang = app.translator.locale;\n $.fancybox.defaults.i18n[app.translator.locale] = {\n NEXT: app.translator.trans('the-turk-fancybox.forum.next'),\n PREV: app.translator.trans('the-turk-fancybox.forum.prev'),\n CLOSE: app.translator.trans('the-turk-fancybox.forum.close'),\n ERROR: app.translator.trans('the-turk-fancybox.forum.error')\n }\n\n const selectors = `\n a.block-image-self-link,\n a.inline-image-self-link,\n a.fancybox--iframe-link,\n a.fancybox--video-link\n `;\n\n extend(CommentPost.prototype, 'config', function(x, isInitialized, context) {\n categorizeImages(this.element);\n\n\n\n $(this.element).find(selectors).click((e) => e.preventDefault());\n\n if (!this.isEditing() && !('fancybox_gallery' in this)) {\n let fancies = $(this.element).find(selectors).not(`\n a.block-image-link *,\n a.inline-image-link *`\n );\n\n let gallery = fancies.map((i, e) => {\n let type;\n let caption = $(e).find('img').attr('title') || $(e).attr('title') || '';\n let src = $(e).attr('href') || $(e).find('img').attr('src');\n\n if ($(e).hasClass('fancybox--iframe-link')) {\n type = 'iframe';\n } else if (!$(e).hasClass('fancybox--video-link')) {\n type = 'image';\n }\n\n return {\n src: src,\n type: type,\n opts : {\n caption : caption\n \t\t}\n }\n });\n\n this.fancybox_gallery = gallery.length ? gallery : false;\n\n if (this.fancybox_gallery) {\n fancies.each((i, e) => {\n let index = i;\n\n $(e).off('click.fancybox');\n $(e).on('click.fancybox', (event) => {\n $.fancybox.open(this.fancybox_gallery, {}, index);\n });\n });\n }\n } else if (this.isEditing() && 'fancybox_gallery' in this) {\n delete this.fancybox_gallery;\n }\n });\n\n extend(ModalManager.prototype, 'show', function (x) {\n $.fancybox.close();\n })\n\n if (s9e && s9e.TextFormatter) {\n extend(s9e.TextFormatter, 'preview', function(x, preview, element) {\n if (element.matches('.Post *'))\n categorizeImages(element);\n });\n }\n});\n","module.exports = flarum.core.compat['components/CommentPost'];","module.exports = flarum.core.compat['components/ModalManager'];","module.exports = flarum.core.compat['extend'];"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://@malago/flancy/webpack/bootstrap","webpack://@malago/flancy/./src/forum/index.js","webpack://@malago/flancy/./forum.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","app","initializers","add","console","log"],"mappings":"2BACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QA0Df,OArDAF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,GAIjBlC,EAAoBA,EAAoBmC,EAAI,G,gBClFrDC,IAAIC,aAAaC,IAAI,iBAAiB,WACpCC,QAAQC,IAAI,qC,6BCDd","file":"forum.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","app.initializers.add('malago/flancy', () => {\r\n console.log('[malago/flancy] Hello, forum!');\r\n});\r\n","export * from './src/forum';\n"],"sourceRoot":""} \ No newline at end of file diff --git a/js/package.json b/js/package.json index fa42fd2..34428e7 100644 --- a/js/package.json +++ b/js/package.json @@ -1,17 +1,17 @@ { - "name": "@the-turk/fancybox", + "name": "@malago/fancybox", "description": "Image formatting and lightbox modal using FancyBox. (see https://fancyapps.com/fancybox)", + "version": "0.2.0-beta.5", "license": "GPL-3.0-or-later", - "version": "0.2.0-beta.4", "dependencies": { - "flarum-webpack-config": "0.1.0-beta.10", + "flarum-webpack-config": "^0.1.0-beta.14", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", "@fancyapps/fancybox": "^3.5.7" }, "repository": { "type": "git", - "url": "git://github.com/the-turk/flarum-ext-fancybox.git" + "url": "git://github.com/malago86/flarum-ext-fancybox.git" }, "scripts": { "dev": "webpack --mode development --watch", diff --git a/js/src/forum/index.js b/js/src/forum/index.js index ba2974c..5089ca9 100644 --- a/js/src/forum/index.js +++ b/js/src/forum/index.js @@ -85,15 +85,15 @@ function categorizeImages(element) { }); } -app.initializers.add('the-turk-fancybox', app => { +app.initializers.add('malago-fancybox', app => { $.fancybox.defaults.toolbar = false; $.fancybox.defaults.smallBtn = true; $.fancybox.defaults.lang = app.translator.locale; $.fancybox.defaults.i18n[app.translator.locale] = { - NEXT: app.translator.trans('the-turk-fancybox.forum.next'), - PREV: app.translator.trans('the-turk-fancybox.forum.prev'), - CLOSE: app.translator.trans('the-turk-fancybox.forum.close'), - ERROR: app.translator.trans('the-turk-fancybox.forum.error') + NEXT: app.translator.trans('malago-fancybox.forum.next'), + PREV: app.translator.trans('malago-fancybox.forum.prev'), + CLOSE: app.translator.trans('malago-fancybox.forum.close'), + ERROR: app.translator.trans('malago-fancybox.forum.error') } const selectors = ` @@ -103,7 +103,7 @@ app.initializers.add('the-turk-fancybox', app => { a.fancybox--video-link `; - extend(CommentPost.prototype, 'config', function(x, isInitialized, context) { + extend(CommentPost.prototype, 'oncreate', function(x, isInitialized, context) { categorizeImages(this.element); $(this.element).find(selectors).click((e) => e.preventDefault()); diff --git a/locale/en.yml b/locale/en.yml index d7055b5..874ccac 100644 --- a/locale/en.yml +++ b/locale/en.yml @@ -1,4 +1,4 @@ -the-turk-fancybox: +malago-fancybox: forum: next: Next prev: Previous diff --git a/locale/tr.yml b/locale/tr.yml index ac27ed6..e93a8d7 100644 --- a/locale/tr.yml +++ b/locale/tr.yml @@ -1,4 +1,4 @@ -the-turk-fancybox: +malago-fancybox: forum: next: Sonraki prev: Önceki diff --git a/src/Listeners/ConfigureTextFormatter.php b/src/Listeners/ConfigureTextFormatter.php index 24d3ff4..1381e10 100644 --- a/src/Listeners/ConfigureTextFormatter.php +++ b/src/Listeners/ConfigureTextFormatter.php @@ -1,5 +1,5 @@