diff --git a/Makefile b/Makefile
index b214814..f02c0c3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,7 @@
COLORBOX_PATH=sigal/themes/colorbox/static/css
GALLERIA_PATH=sigal/themes/galleria/static/css
-PHOTOSWIPE_PATH=sigal/themes/photoswipe/static
-all: colorbox galleria photoswipe
+all: colorbox galleria
init:
pip install -r requirements.txt
@@ -16,18 +15,15 @@ colorbox:
galleria:
cat $(GALLERIA_PATH)/{normalize,style}.css | cssmin > $(GALLERIA_PATH)/style.min.css
-photoswipe:
- cat $(PHOTOSWIPE_PATH)/styles.css $(PHOTOSWIPE_PATH)/default-skin/default-skin.css $(PHOTOSWIPE_PATH)/photoswipe.css | cssmin > $(PHOTOSWIPE_PATH)/styles.min.css
-
test:
py.test
coverage:
py.test --cov sigal --cov-report term --cov-report=html
-publish: colorbox galleria photoswipe
+publish: colorbox galleria
python setup.py register
python setup.py sdist bdist_wheel
twine upload dist/*
-.PHONY: colorbox galleria photoswipe docs
+.PHONY: colorbox galleria docs
diff --git a/sigal/themes/colorbox/static/js/jquery.colorbox.min.js b/sigal/themes/colorbox/static/js/jquery.colorbox-min.js
similarity index 100%
rename from sigal/themes/colorbox/static/js/jquery.colorbox.min.js
rename to sigal/themes/colorbox/static/js/jquery.colorbox-min.js
diff --git a/sigal/themes/colorbox/static/js/jquery.colorbox.js b/sigal/themes/colorbox/static/js/jquery.colorbox.js
new file mode 100644
index 0000000..12dd1b2
--- /dev/null
+++ b/sigal/themes/colorbox/static/js/jquery.colorbox.js
@@ -0,0 +1,1105 @@
+/*!
+ Colorbox 1.6.4
+ license: MIT
+ http://www.jacklmoore.com/colorbox
+*/
+(function ($, document, window) {
+ var
+ // Default settings object.
+ // See http://jacklmoore.com/colorbox for details.
+ defaults = {
+ // data sources
+ html: false,
+ photo: false,
+ iframe: false,
+ inline: false,
+
+ // behavior and appearance
+ transition: "elastic",
+ speed: 300,
+ fadeOut: 300,
+ width: false,
+ initialWidth: "600",
+ innerWidth: false,
+ maxWidth: false,
+ height: false,
+ initialHeight: "450",
+ innerHeight: false,
+ maxHeight: false,
+ scalePhotos: true,
+ scrolling: true,
+ opacity: 0.9,
+ preloading: true,
+ className: false,
+ overlayClose: true,
+ escKey: true,
+ arrowKey: true,
+ top: false,
+ bottom: false,
+ left: false,
+ right: false,
+ fixed: false,
+ data: undefined,
+ closeButton: true,
+ fastIframe: true,
+ open: false,
+ reposition: true,
+ loop: true,
+ slideshow: false,
+ slideshowAuto: true,
+ slideshowSpeed: 2500,
+ slideshowStart: "start slideshow",
+ slideshowStop: "stop slideshow",
+ photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,
+
+ // alternate image paths for high-res displays
+ retinaImage: false,
+ retinaUrl: false,
+ retinaSuffix: '@2x.$1',
+
+ // internationalization
+ current: "image {current} of {total}",
+ previous: "previous",
+ next: "next",
+ close: "close",
+ xhrError: "This content failed to load.",
+ imgError: "This image failed to load.",
+
+ // accessbility
+ returnFocus: true,
+ trapFocus: true,
+
+ // callbacks
+ onOpen: false,
+ onLoad: false,
+ onComplete: false,
+ onCleanup: false,
+ onClosed: false,
+
+ rel: function() {
+ return this.rel;
+ },
+ href: function() {
+ // using this.href would give the absolute url, when the href may have been inteded as a selector (e.g. '#container')
+ return $(this).attr('href');
+ },
+ title: function() {
+ return this.title;
+ },
+ createImg: function() {
+ var img = new Image();
+ var attrs = $(this).data('cbox-img-attrs');
+
+ if (typeof attrs === 'object') {
+ $.each(attrs, function(key, val){
+ img[key] = val;
+ });
+ }
+
+ return img;
+ },
+ createIframe: function() {
+ var iframe = document.createElement('iframe');
+ var attrs = $(this).data('cbox-iframe-attrs');
+
+ if (typeof attrs === 'object') {
+ $.each(attrs, function(key, val){
+ iframe[key] = val;
+ });
+ }
+
+ if ('frameBorder' in iframe) {
+ iframe.frameBorder = 0;
+ }
+ if ('allowTransparency' in iframe) {
+ iframe.allowTransparency = "true";
+ }
+ iframe.name = (new Date()).getTime(); // give the iframe a unique name to prevent caching
+ iframe.allowFullscreen = true;
+
+ return iframe;
+ }
+ },
+
+ // Abstracting the HTML and event identifiers for easy rebranding
+ colorbox = 'colorbox',
+ prefix = 'cbox',
+ boxElement = prefix + 'Element',
+
+ // Events
+ event_open = prefix + '_open',
+ event_load = prefix + '_load',
+ event_complete = prefix + '_complete',
+ event_cleanup = prefix + '_cleanup',
+ event_closed = prefix + '_closed',
+ event_purge = prefix + '_purge',
+
+ // Cached jQuery Object Variables
+ $overlay,
+ $box,
+ $wrap,
+ $content,
+ $topBorder,
+ $leftBorder,
+ $rightBorder,
+ $bottomBorder,
+ $related,
+ $window,
+ $loaded,
+ $loadingBay,
+ $loadingOverlay,
+ $title,
+ $current,
+ $slideshow,
+ $next,
+ $prev,
+ $close,
+ $groupControls,
+ $events = $(''), // $({}) would be prefered, but there is an issue with jQuery 1.4.2
+
+ // Variables for cached values or use across multiple functions
+ settings,
+ interfaceHeight,
+ interfaceWidth,
+ loadedHeight,
+ loadedWidth,
+ index,
+ photo,
+ open,
+ active,
+ closing,
+ loadingTimer,
+ publicMethod,
+ div = "div",
+ requests = 0,
+ previousCSS = {},
+ init;
+
+ // ****************
+ // HELPER FUNCTIONS
+ // ****************
+
+ // Convenience function for creating new jQuery objects
+ function $tag(tag, id, css) {
+ var element = document.createElement(tag);
+
+ if (id) {
+ element.id = prefix + id;
+ }
+
+ if (css) {
+ element.style.cssText = css;
+ }
+
+ return $(element);
+ }
+
+ // Get the window height using innerHeight when available to avoid an issue with iOS
+ // http://bugs.jquery.com/ticket/6724
+ function winheight() {
+ return window.innerHeight ? window.innerHeight : $(window).height();
+ }
+
+ function Settings(element, options) {
+ if (options !== Object(options)) {
+ options = {};
+ }
+
+ this.cache = {};
+ this.el = element;
+
+ this.value = function(key) {
+ var dataAttr;
+
+ if (this.cache[key] === undefined) {
+ dataAttr = $(this.el).attr('data-cbox-'+key);
+
+ if (dataAttr !== undefined) {
+ this.cache[key] = dataAttr;
+ } else if (options[key] !== undefined) {
+ this.cache[key] = options[key];
+ } else if (defaults[key] !== undefined) {
+ this.cache[key] = defaults[key];
+ }
+ }
+
+ return this.cache[key];
+ };
+
+ this.get = function(key) {
+ var value = this.value(key);
+ return $.isFunction(value) ? value.call(this.el, this) : value;
+ };
+ }
+
+ // Determine the next and previous members in a group.
+ function getIndex(increment) {
+ var
+ max = $related.length,
+ newIndex = (index + increment) % max;
+
+ return (newIndex < 0) ? max + newIndex : newIndex;
+ }
+
+ // Convert '%' and 'px' values to integers
+ function setSize(size, dimension) {
+ return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10));
+ }
+
+ // Checks an href to see if it is a photo.
+ // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex.
+ function isImage(settings, url) {
+ return settings.get('photo') || settings.get('photoRegex').test(url);
+ }
+
+ function retinaUrl(settings, url) {
+ return settings.get('retinaUrl') && window.devicePixelRatio > 1 ? url.replace(settings.get('photoRegex'), settings.get('retinaSuffix')) : url;
+ }
+
+ function trapFocus(e) {
+ if ('contains' in $box[0] && !$box[0].contains(e.target) && e.target !== $overlay[0]) {
+ e.stopPropagation();
+ $box.focus();
+ }
+ }
+
+ function setClass(str) {
+ if (setClass.str !== str) {
+ $box.add($overlay).removeClass(setClass.str).addClass(str);
+ setClass.str = str;
+ }
+ }
+
+ function getRelated(rel) {
+ index = 0;
+
+ if (rel && rel !== false && rel !== 'nofollow') {
+ $related = $('.' + boxElement).filter(function () {
+ var options = $.data(this, colorbox);
+ var settings = new Settings(this, options);
+ return (settings.get('rel') === rel);
+ });
+ index = $related.index(settings.el);
+
+ // Check direct calls to Colorbox.
+ if (index === -1) {
+ $related = $related.add(settings.el);
+ index = $related.length - 1;
+ }
+ } else {
+ $related = $(settings.el);
+ }
+ }
+
+ function trigger(event) {
+ // for external use
+ $(document).trigger(event);
+ // for internal use
+ $events.triggerHandler(event);
+ }
+
+ var slideshow = (function(){
+ var active,
+ className = prefix + "Slideshow_",
+ click = "click." + prefix,
+ timeOut;
+
+ function clear () {
+ clearTimeout(timeOut);
+ }
+
+ function set() {
+ if (settings.get('loop') || $related[index + 1]) {
+ clear();
+ timeOut = setTimeout(publicMethod.next, settings.get('slideshowSpeed'));
+ }
+ }
+
+ function start() {
+ $slideshow
+ .html(settings.get('slideshowStop'))
+ .unbind(click)
+ .one(click, stop);
+
+ $events
+ .bind(event_complete, set)
+ .bind(event_load, clear);
+
+ $box.removeClass(className + "off").addClass(className + "on");
+ }
+
+ function stop() {
+ clear();
+
+ $events
+ .unbind(event_complete, set)
+ .unbind(event_load, clear);
+
+ $slideshow
+ .html(settings.get('slideshowStart'))
+ .unbind(click)
+ .one(click, function () {
+ publicMethod.next();
+ start();
+ });
+
+ $box.removeClass(className + "on").addClass(className + "off");
+ }
+
+ function reset() {
+ active = false;
+ $slideshow.hide();
+ clear();
+ $events
+ .unbind(event_complete, set)
+ .unbind(event_load, clear);
+ $box.removeClass(className + "off " + className + "on");
+ }
+
+ return function(){
+ if (active) {
+ if (!settings.get('slideshow')) {
+ $events.unbind(event_cleanup, reset);
+ reset();
+ }
+ } else {
+ if (settings.get('slideshow') && $related[1]) {
+ active = true;
+ $events.one(event_cleanup, reset);
+ if (settings.get('slideshowAuto')) {
+ start();
+ } else {
+ stop();
+ }
+ $slideshow.show();
+ }
+ }
+ };
+
+ }());
+
+
+ function launch(element) {
+ var options;
+
+ if (!closing) {
+
+ options = $(element).data(colorbox);
+
+ settings = new Settings(element, options);
+
+ getRelated(settings.get('rel'));
+
+ if (!open) {
+ open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys.
+
+ setClass(settings.get('className'));
+
+ // Show colorbox so the sizes can be calculated in older versions of jQuery
+ $box.css({visibility:'hidden', display:'block', opacity:''});
+
+ $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden; visibility:hidden');
+ $content.css({width:'', height:''}).append($loaded);
+
+ // Cache values needed for size calculations
+ interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();
+ interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();
+ loadedHeight = $loaded.outerHeight(true);
+ loadedWidth = $loaded.outerWidth(true);
+
+ // Opens inital empty Colorbox prior to content being loaded.
+ var initialWidth = setSize(settings.get('initialWidth'), 'x');
+ var initialHeight = setSize(settings.get('initialHeight'), 'y');
+ var maxWidth = settings.get('maxWidth');
+ var maxHeight = settings.get('maxHeight');
+
+ settings.w = Math.max((maxWidth !== false ? Math.min(initialWidth, setSize(maxWidth, 'x')) : initialWidth) - loadedWidth - interfaceWidth, 0);
+ settings.h = Math.max((maxHeight !== false ? Math.min(initialHeight, setSize(maxHeight, 'y')) : initialHeight) - loadedHeight - interfaceHeight, 0);
+
+ $loaded.css({width:'', height:settings.h});
+ publicMethod.position();
+
+ trigger(event_open);
+ settings.get('onOpen');
+
+ $groupControls.add($title).hide();
+
+ $box.focus();
+
+ if (settings.get('trapFocus')) {
+ // Confine focus to the modal
+ // Uses event capturing that is not supported in IE8-
+ if (document.addEventListener) {
+
+ document.addEventListener('focus', trapFocus, true);
+
+ $events.one(event_closed, function () {
+ document.removeEventListener('focus', trapFocus, true);
+ });
+ }
+ }
+
+ // Return focus on closing
+ if (settings.get('returnFocus')) {
+ $events.one(event_closed, function () {
+ $(settings.el).focus();
+ });
+ }
+ }
+
+ var opacity = parseFloat(settings.get('opacity'));
+ $overlay.css({
+ opacity: opacity === opacity ? opacity : '',
+ cursor: settings.get('overlayClose') ? 'pointer' : '',
+ visibility: 'visible'
+ }).show();
+
+ if (settings.get('closeButton')) {
+ $close.html(settings.get('close')).appendTo($content);
+ } else {
+ $close.appendTo('
').hide().insertBefore($target);
+
+ $events.one(event_purge, function () {
+ $inline.replaceWith($target);
+ });
+
+ prep($target);
+ } else if (settings.get('iframe')) {
+ // IFrame element won't be added to the DOM until it is ready to be displayed,
+ // to avoid problems with DOM-ready JS that might be trying to run in that iframe.
+ prep(" ");
+ } else if (settings.get('html')) {
+ prep(settings.get('html'));
+ } else if (isImage(settings, href)) {
+
+ href = retinaUrl(settings, href);
+
+ photo = settings.get('createImg');
+
+ $(photo)
+ .addClass(prefix + 'Photo')
+ .bind('error.'+prefix,function () {
+ prep($tag(div, 'Error').html(settings.get('imgError')));
+ })
+ .one('load', function () {
+ if (request !== requests) {
+ return;
+ }
+
+ // A small pause because some browsers will occassionaly report a
+ // img.width and img.height of zero immediately after the img.onload fires
+ setTimeout(function(){
+ var percent;
+
+ if (settings.get('retinaImage') && window.devicePixelRatio > 1) {
+ photo.height = photo.height / window.devicePixelRatio;
+ photo.width = photo.width / window.devicePixelRatio;
+ }
+
+ if (settings.get('scalePhotos')) {
+ setResize = function () {
+ photo.height -= photo.height * percent;
+ photo.width -= photo.width * percent;
+ };
+ if (settings.mw && photo.width > settings.mw) {
+ percent = (photo.width - settings.mw) / photo.width;
+ setResize();
+ }
+ if (settings.mh && photo.height > settings.mh) {
+ percent = (photo.height - settings.mh) / photo.height;
+ setResize();
+ }
+ }
+
+ if (settings.h) {
+ photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px';
+ }
+
+ if ($related[1] && (settings.get('loop') || $related[index + 1])) {
+ photo.style.cursor = 'pointer';
+
+ $(photo).bind('click.'+prefix, function () {
+ publicMethod.next();
+ });
+ }
+
+ photo.style.width = photo.width + 'px';
+ photo.style.height = photo.height + 'px';
+ prep(photo);
+ }, 1);
+ });
+
+ photo.src = href;
+
+ } else if (href) {
+ $loadingBay.load(href, settings.get('data'), function (data, status) {
+ if (request === requests) {
+ prep(status === 'error' ? $tag(div, 'Error').html(settings.get('xhrError')) : $(this).contents());
+ }
+ });
+ }
+ }
+
+ // Navigates to the next page/image in a set.
+ publicMethod.next = function () {
+ if (!active && $related[1] && (settings.get('loop') || $related[index + 1])) {
+ index = getIndex(1);
+ launch($related[index]);
+ }
+ };
+
+ publicMethod.prev = function () {
+ if (!active && $related[1] && (settings.get('loop') || index)) {
+ index = getIndex(-1);
+ launch($related[index]);
+ }
+ };
+
+ // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close();
+ publicMethod.close = function () {
+ if (open && !closing) {
+
+ closing = true;
+ open = false;
+ trigger(event_cleanup);
+ settings.get('onCleanup');
+ $window.unbind('.' + prefix);
+ $overlay.fadeTo(settings.get('fadeOut') || 0, 0);
+
+ $box.stop().fadeTo(settings.get('fadeOut') || 0, 0, function () {
+ $box.hide();
+ $overlay.hide();
+ trigger(event_purge);
+ $loaded.remove();
+
+ setTimeout(function () {
+ closing = false;
+ trigger(event_closed);
+ settings.get('onClosed');
+ }, 1);
+ });
+ }
+ };
+
+ // Removes changes Colorbox made to the document, but does not remove the plugin.
+ publicMethod.remove = function () {
+ if (!$box) { return; }
+
+ $box.stop();
+ $[colorbox].close();
+ $box.stop(false, true).remove();
+ $overlay.remove();
+ closing = false;
+ $box = null;
+ $('.' + boxElement)
+ .removeData(colorbox)
+ .removeClass(boxElement);
+
+ $(document).unbind('click.'+prefix).unbind('keydown.'+prefix);
+ };
+
+ // A method for fetching the current element Colorbox is referencing.
+ // returns a jQuery object.
+ publicMethod.element = function () {
+ return $(settings.el);
+ };
+
+ publicMethod.settings = defaults;
+
+}(jQuery, document, window));
diff --git a/sigal/themes/colorbox/templates/index.html b/sigal/themes/colorbox/templates/index.html
index 173c9e8..c706c33 100644
--- a/sigal/themes/colorbox/templates/index.html
+++ b/sigal/themes/colorbox/templates/index.html
@@ -114,7 +114,7 @@
{% else %}
{% endif %}
-
+
{% if 'sigal.plugins.media_page' in settings.plugins %}
diff --git a/sigal/themes/photoswipe/static/default-skin/default-skin.css b/sigal/themes/photoswipe/static/default-skin/default-skin.css
index 3b74eb6..c961632 100644
--- a/sigal/themes/photoswipe/static/default-skin/default-skin.css
+++ b/sigal/themes/photoswipe/static/default-skin/default-skin.css
@@ -12,7 +12,7 @@
*/
/*
-
+
1. Buttons
*/
@@ -35,8 +35,7 @@
transition: opacity 0.2s;
-webkit-box-shadow: none;
box-shadow: none; }
- .pswp__button:focus,
- .pswp__button:hover {
+ .pswp__button:focus, .pswp__button:hover {
opacity: 1; }
.pswp__button:active {
outline: none;
@@ -52,7 +51,7 @@
.pswp__button,
.pswp__button--arrow--left:before,
.pswp__button--arrow--right:before {
- background: url(default-skin/default-skin.png) 0 0 no-repeat;
+ background: url(default-skin.png) 0 0 no-repeat;
background-size: 264px 88px;
width: 44px;
height: 44px; }
@@ -62,7 +61,7 @@
.pswp--svg .pswp__button,
.pswp--svg .pswp__button--arrow--left:before,
.pswp--svg .pswp__button--arrow--right:before {
- background-image: url(default-skin/default-skin.svg); }
+ background-image: url(default-skin.svg); }
.pswp--svg .pswp__button--arrow--left,
.pswp--svg .pswp__button--arrow--right {
background: none; } }
@@ -257,7 +256,7 @@ a.pswp__share--download:hover {
padding: 0 10px; }
/*
-
+
4. Caption
*/
@@ -338,8 +337,8 @@ a.pswp__share--download:hover {
margin: 0; }
.pswp--css_animation .pswp__preloader__cut {
- /*
- The idea of animating inner circle is based on Polymer ("material") loading indicator
+ /*
+ The idea of animating inner circle is based on Polymer ("material") loading indicator
by Keanu Lee https://blog.keanulee.com/2014/10/20/the-tale-of-three-spinners.html
*/
position: relative;
@@ -409,7 +408,7 @@ a.pswp__share--download:hover {
transform: rotate(0); } }
/*
-
+
6. Additional styles
*/
diff --git a/sigal/themes/photoswipe/static/photoswipe-ui-default.js b/sigal/themes/photoswipe/static/photoswipe-ui-default.js
new file mode 100644
index 0000000..9799dd4
--- /dev/null
+++ b/sigal/themes/photoswipe/static/photoswipe-ui-default.js
@@ -0,0 +1,861 @@
+/*! PhotoSwipe Default UI - 4.1.2 - 2017-04-05
+* http://photoswipe.com
+* Copyright (c) 2017 Dmitry Semenov; */
+/**
+*
+* UI on top of main sliding area (caption, arrows, close button, etc.).
+* Built just using public methods/properties of PhotoSwipe.
+*
+*/
+(function (root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ define(factory);
+ } else if (typeof exports === 'object') {
+ module.exports = factory();
+ } else {
+ root.PhotoSwipeUI_Default = factory();
+ }
+})(this, function () {
+
+ 'use strict';
+
+
+
+var PhotoSwipeUI_Default =
+ function(pswp, framework) {
+
+ var ui = this;
+ var _overlayUIUpdated = false,
+ _controlsVisible = true,
+ _fullscrenAPI,
+ _controls,
+ _captionContainer,
+ _fakeCaptionContainer,
+ _indexIndicator,
+ _shareButton,
+ _shareModal,
+ _shareModalHidden = true,
+ _initalCloseOnScrollValue,
+ _isIdle,
+ _listen,
+
+ _loadingIndicator,
+ _loadingIndicatorHidden,
+ _loadingIndicatorTimeout,
+
+ _galleryHasOneSlide,
+
+ _options,
+ _defaultUIOptions = {
+ barsSize: {top:44, bottom:'auto'},
+ closeElClasses: ['item', 'caption', 'zoom-wrap', 'ui', 'top-bar'],
+ timeToIdle: 4000,
+ timeToIdleOutside: 1000,
+ loadingIndicatorDelay: 1000, // 2s
+
+ addCaptionHTMLFn: function(item, captionEl /*, isFake */) {
+ if(!item.title) {
+ captionEl.children[0].innerHTML = '';
+ return false;
+ }
+ captionEl.children[0].innerHTML = item.title;
+ return true;
+ },
+
+ closeEl:true,
+ captionEl: true,
+ fullscreenEl: true,
+ zoomEl: true,
+ shareEl: true,
+ counterEl: true,
+ arrowEl: true,
+ preloaderEl: true,
+
+ tapToClose: false,
+ tapToToggleControls: true,
+
+ clickToCloseNonZoomable: true,
+
+ shareButtons: [
+ {id:'facebook', label:'Share on Facebook', url:'https://www.facebook.com/sharer/sharer.php?u={{url}}'},
+ {id:'twitter', label:'Tweet', url:'https://twitter.com/intent/tweet?text={{text}}&url={{url}}'},
+ {id:'pinterest', label:'Pin it', url:'http://www.pinterest.com/pin/create/button/'+
+ '?url={{url}}&media={{image_url}}&description={{text}}'},
+ {id:'download', label:'Download image', url:'{{raw_image_url}}', download:true}
+ ],
+ getImageURLForShare: function( /* shareButtonData */ ) {
+ return pswp.currItem.src || '';
+ },
+ getPageURLForShare: function( /* shareButtonData */ ) {
+ return window.location.href;
+ },
+ getTextForShare: function( /* shareButtonData */ ) {
+ return pswp.currItem.title || '';
+ },
+
+ indexIndicatorSep: ' / ',
+ fitControlsWidth: 1200
+
+ },
+ _blockControlsTap,
+ _blockControlsTapTimeout;
+
+
+
+ var _onControlsTap = function(e) {
+ if(_blockControlsTap) {
+ return true;
+ }
+
+
+ e = e || window.event;
+
+ if(_options.timeToIdle && _options.mouseUsed && !_isIdle) {
+ // reset idle timer
+ _onIdleMouseMove();
+ }
+
+
+ var target = e.target || e.srcElement,
+ uiElement,
+ clickedClass = target.getAttribute('class') || '',
+ found;
+
+ for(var i = 0; i < _uiElements.length; i++) {
+ uiElement = _uiElements[i];
+ if(uiElement.onTap && clickedClass.indexOf('pswp__' + uiElement.name ) > -1 ) {
+ uiElement.onTap();
+ found = true;
+
+ }
+ }
+
+ if(found) {
+ if(e.stopPropagation) {
+ e.stopPropagation();
+ }
+ _blockControlsTap = true;
+
+ // Some versions of Android don't prevent ghost click event
+ // when preventDefault() was called on touchstart and/or touchend.
+ //
+ // This happens on v4.3, 4.2, 4.1,
+ // older versions strangely work correctly,
+ // but just in case we add delay on all of them)
+ var tapDelay = framework.features.isOldAndroid ? 600 : 30;
+ _blockControlsTapTimeout = setTimeout(function() {
+ _blockControlsTap = false;
+ }, tapDelay);
+ }
+
+ },
+ _fitControlsInViewport = function() {
+ return !pswp.likelyTouchDevice || _options.mouseUsed || screen.width > _options.fitControlsWidth;
+ },
+ _togglePswpClass = function(el, cName, add) {
+ framework[ (add ? 'add' : 'remove') + 'Class' ](el, 'pswp__' + cName);
+ },
+
+ // add class when there is just one item in the gallery
+ // (by default it hides left/right arrows and 1ofX counter)
+ _countNumItems = function() {
+ var hasOneSlide = (_options.getNumItemsFn() === 1);
+
+ if(hasOneSlide !== _galleryHasOneSlide) {
+ _togglePswpClass(_controls, 'ui--one-slide', hasOneSlide);
+ _galleryHasOneSlide = hasOneSlide;
+ }
+ },
+ _toggleShareModalClass = function() {
+ _togglePswpClass(_shareModal, 'share-modal--hidden', _shareModalHidden);
+ },
+ _toggleShareModal = function() {
+
+ _shareModalHidden = !_shareModalHidden;
+
+
+ if(!_shareModalHidden) {
+ _toggleShareModalClass();
+ setTimeout(function() {
+ if(!_shareModalHidden) {
+ framework.addClass(_shareModal, 'pswp__share-modal--fade-in');
+ }
+ }, 30);
+ } else {
+ framework.removeClass(_shareModal, 'pswp__share-modal--fade-in');
+ setTimeout(function() {
+ if(_shareModalHidden) {
+ _toggleShareModalClass();
+ }
+ }, 300);
+ }
+
+ if(!_shareModalHidden) {
+ _updateShareURLs();
+ }
+ return false;
+ },
+
+ _openWindowPopup = function(e) {
+ e = e || window.event;
+ var target = e.target || e.srcElement;
+
+ pswp.shout('shareLinkClick', e, target);
+
+ if(!target.href) {
+ return false;
+ }
+
+ if( target.hasAttribute('download') ) {
+ return true;
+ }
+
+ window.open(target.href, 'pswp_share', 'scrollbars=yes,resizable=yes,toolbar=no,'+
+ 'location=yes,width=550,height=420,top=100,left=' +
+ (window.screen ? Math.round(screen.width / 2 - 275) : 100) );
+
+ if(!_shareModalHidden) {
+ _toggleShareModal();
+ }
+
+ return false;
+ },
+ _updateShareURLs = function() {
+ var shareButtonOut = '',
+ shareButtonData,
+ shareURL,
+ image_url,
+ page_url,
+ share_text;
+
+ for(var i = 0; i < _options.shareButtons.length; i++) {
+ shareButtonData = _options.shareButtons[i];
+
+ image_url = _options.getImageURLForShare(shareButtonData);
+ page_url = _options.getPageURLForShare(shareButtonData);
+ share_text = _options.getTextForShare(shareButtonData);
+
+ shareURL = shareButtonData.url.replace('{{url}}', encodeURIComponent(page_url) )
+ .replace('{{image_url}}', encodeURIComponent(image_url) )
+ .replace('{{raw_image_url}}', image_url )
+ .replace('{{text}}', encodeURIComponent(share_text) );
+
+ shareButtonOut += '
' +
+ shareButtonData.label + '';
+
+ if(_options.parseShareButtonOut) {
+ shareButtonOut = _options.parseShareButtonOut(shareButtonData, shareButtonOut);
+ }
+ }
+ _shareModal.children[0].innerHTML = shareButtonOut;
+ _shareModal.children[0].onclick = _openWindowPopup;
+
+ },
+ _hasCloseClass = function(target) {
+ for(var i = 0; i < _options.closeElClasses.length; i++) {
+ if( framework.hasClass(target, 'pswp__' + _options.closeElClasses[i]) ) {
+ return true;
+ }
+ }
+ },
+ _idleInterval,
+ _idleTimer,
+ _idleIncrement = 0,
+ _onIdleMouseMove = function() {
+ clearTimeout(_idleTimer);
+ _idleIncrement = 0;
+ if(_isIdle) {
+ ui.setIdle(false);
+ }
+ },
+ _onMouseLeaveWindow = function(e) {
+ e = e ? e : window.event;
+ var from = e.relatedTarget || e.toElement;
+ if (!from || from.nodeName === 'HTML') {
+ clearTimeout(_idleTimer);
+ _idleTimer = setTimeout(function() {
+ ui.setIdle(true);
+ }, _options.timeToIdleOutside);
+ }
+ },
+ _setupFullscreenAPI = function() {
+ if(_options.fullscreenEl && !framework.features.isOldAndroid) {
+ if(!_fullscrenAPI) {
+ _fullscrenAPI = ui.getFullscreenAPI();
+ }
+ if(_fullscrenAPI) {
+ framework.bind(document, _fullscrenAPI.eventK, ui.updateFullscreen);
+ ui.updateFullscreen();
+ framework.addClass(pswp.template, 'pswp--supports-fs');
+ } else {
+ framework.removeClass(pswp.template, 'pswp--supports-fs');
+ }
+ }
+ },
+ _setupLoadingIndicator = function() {
+ // Setup loading indicator
+ if(_options.preloaderEl) {
+
+ _toggleLoadingIndicator(true);
+
+ _listen('beforeChange', function() {
+
+ clearTimeout(_loadingIndicatorTimeout);
+
+ // display loading indicator with delay
+ _loadingIndicatorTimeout = setTimeout(function() {
+
+ if(pswp.currItem && pswp.currItem.loading) {
+
+ if( !pswp.allowProgressiveImg() || (pswp.currItem.img && !pswp.currItem.img.naturalWidth) ) {
+ // show preloader if progressive loading is not enabled,
+ // or image width is not defined yet (because of slow connection)
+ _toggleLoadingIndicator(false);
+ // items-controller.js function allowProgressiveImg
+ }
+
+ } else {
+ _toggleLoadingIndicator(true); // hide preloader
+ }
+
+ }, _options.loadingIndicatorDelay);
+
+ });
+ _listen('imageLoadComplete', function(index, item) {
+ if(pswp.currItem === item) {
+ _toggleLoadingIndicator(true);
+ }
+ });
+
+ }
+ },
+ _toggleLoadingIndicator = function(hide) {
+ if( _loadingIndicatorHidden !== hide ) {
+ _togglePswpClass(_loadingIndicator, 'preloader--active', !hide);
+ _loadingIndicatorHidden = hide;
+ }
+ },
+ _applyNavBarGaps = function(item) {
+ var gap = item.vGap;
+
+ if( _fitControlsInViewport() ) {
+
+ var bars = _options.barsSize;
+ if(_options.captionEl && bars.bottom === 'auto') {
+ if(!_fakeCaptionContainer) {
+ _fakeCaptionContainer = framework.createEl('pswp__caption pswp__caption--fake');
+ _fakeCaptionContainer.appendChild( framework.createEl('pswp__caption__center') );
+ _controls.insertBefore(_fakeCaptionContainer, _captionContainer);
+ framework.addClass(_controls, 'pswp__ui--fit');
+ }
+ if( _options.addCaptionHTMLFn(item, _fakeCaptionContainer, true) ) {
+
+ var captionSize = _fakeCaptionContainer.clientHeight;
+ gap.bottom = parseInt(captionSize,10) || 44;
+ } else {
+ gap.bottom = bars.top; // if no caption, set size of bottom gap to size of top
+ }
+ } else {
+ gap.bottom = bars.bottom === 'auto' ? 0 : bars.bottom;
+ }
+
+ // height of top bar is static, no need to calculate it
+ gap.top = bars.top;
+ } else {
+ gap.top = gap.bottom = 0;
+ }
+ },
+ _setupIdle = function() {
+ // Hide controls when mouse is used
+ if(_options.timeToIdle) {
+ _listen('mouseUsed', function() {
+
+ framework.bind(document, 'mousemove', _onIdleMouseMove);
+ framework.bind(document, 'mouseout', _onMouseLeaveWindow);
+
+ _idleInterval = setInterval(function() {
+ _idleIncrement++;
+ if(_idleIncrement === 2) {
+ ui.setIdle(true);
+ }
+ }, _options.timeToIdle / 2);
+ });
+ }
+ },
+ _setupHidingControlsDuringGestures = function() {
+
+ // Hide controls on vertical drag
+ _listen('onVerticalDrag', function(now) {
+ if(_controlsVisible && now < 0.95) {
+ ui.hideControls();
+ } else if(!_controlsVisible && now >= 0.95) {
+ ui.showControls();
+ }
+ });
+
+ // Hide controls when pinching to close
+ var pinchControlsHidden;
+ _listen('onPinchClose' , function(now) {
+ if(_controlsVisible && now < 0.9) {
+ ui.hideControls();
+ pinchControlsHidden = true;
+ } else if(pinchControlsHidden && !_controlsVisible && now > 0.9) {
+ ui.showControls();
+ }
+ });
+
+ _listen('zoomGestureEnded', function() {
+ pinchControlsHidden = false;
+ if(pinchControlsHidden && !_controlsVisible) {
+ ui.showControls();
+ }
+ });
+
+ };
+
+
+
+ var _uiElements = [
+ {
+ name: 'caption',
+ option: 'captionEl',
+ onInit: function(el) {
+ _captionContainer = el;
+ }
+ },
+ {
+ name: 'share-modal',
+ option: 'shareEl',
+ onInit: function(el) {
+ _shareModal = el;
+ },
+ onTap: function() {
+ _toggleShareModal();
+ }
+ },
+ {
+ name: 'button--share',
+ option: 'shareEl',
+ onInit: function(el) {
+ _shareButton = el;
+ },
+ onTap: function() {
+ _toggleShareModal();
+ }
+ },
+ {
+ name: 'button--zoom',
+ option: 'zoomEl',
+ onTap: pswp.toggleDesktopZoom
+ },
+ {
+ name: 'counter',
+ option: 'counterEl',
+ onInit: function(el) {
+ _indexIndicator = el;
+ }
+ },
+ {
+ name: 'button--close',
+ option: 'closeEl',
+ onTap: pswp.close
+ },
+ {
+ name: 'button--arrow--left',
+ option: 'arrowEl',
+ onTap: pswp.prev
+ },
+ {
+ name: 'button--arrow--right',
+ option: 'arrowEl',
+ onTap: pswp.next
+ },
+ {
+ name: 'button--fs',
+ option: 'fullscreenEl',
+ onTap: function() {
+ if(_fullscrenAPI.isFullscreen()) {
+ _fullscrenAPI.exit();
+ } else {
+ _fullscrenAPI.enter();
+ }
+ }
+ },
+ {
+ name: 'preloader',
+ option: 'preloaderEl',
+ onInit: function(el) {
+ _loadingIndicator = el;
+ }
+ }
+
+ ];
+
+ var _setupUIElements = function() {
+ var item,
+ classAttr,
+ uiElement;
+
+ var loopThroughChildElements = function(sChildren) {
+ if(!sChildren) {
+ return;
+ }
+
+ var l = sChildren.length;
+ for(var i = 0; i < l; i++) {
+ item = sChildren[i];
+ classAttr = item.className;
+
+ for(var a = 0; a < _uiElements.length; a++) {
+ uiElement = _uiElements[a];
+
+ if(classAttr.indexOf('pswp__' + uiElement.name) > -1 ) {
+
+ if( _options[uiElement.option] ) { // if element is not disabled from options
+
+ framework.removeClass(item, 'pswp__element--disabled');
+ if(uiElement.onInit) {
+ uiElement.onInit(item);
+ }
+
+ //item.style.display = 'block';
+ } else {
+ framework.addClass(item, 'pswp__element--disabled');
+ //item.style.display = 'none';
+ }
+ }
+ }
+ }
+ };
+ loopThroughChildElements(_controls.children);
+
+ var topBar = framework.getChildByClass(_controls, 'pswp__top-bar');
+ if(topBar) {
+ loopThroughChildElements( topBar.children );
+ }
+ };
+
+
+
+
+ ui.init = function() {
+
+ // extend options
+ framework.extend(pswp.options, _defaultUIOptions, true);
+
+ // create local link for fast access
+ _options = pswp.options;
+
+ // find pswp__ui element
+ _controls = framework.getChildByClass(pswp.scrollWrap, 'pswp__ui');
+
+ // create local link
+ _listen = pswp.listen;
+
+
+ _setupHidingControlsDuringGestures();
+
+ // update controls when slides change
+ _listen('beforeChange', ui.update);
+
+ // toggle zoom on double-tap
+ _listen('doubleTap', function(point) {
+ var initialZoomLevel = pswp.currItem.initialZoomLevel;
+ if(pswp.getZoomLevel() !== initialZoomLevel) {
+ pswp.zoomTo(initialZoomLevel, point, 333);
+ } else {
+ pswp.zoomTo(_options.getDoubleTapZoom(false, pswp.currItem), point, 333);
+ }
+ });
+
+ // Allow text selection in caption
+ _listen('preventDragEvent', function(e, isDown, preventObj) {
+ var t = e.target || e.srcElement;
+ if(
+ t &&
+ t.getAttribute('class') && e.type.indexOf('mouse') > -1 &&
+ ( t.getAttribute('class').indexOf('__caption') > 0 || (/(SMALL|STRONG|EM)/i).test(t.tagName) )
+ ) {
+ preventObj.prevent = false;
+ }
+ });
+
+ // bind events for UI
+ _listen('bindEvents', function() {
+ framework.bind(_controls, 'pswpTap click', _onControlsTap);
+ framework.bind(pswp.scrollWrap, 'pswpTap', ui.onGlobalTap);
+
+ if(!pswp.likelyTouchDevice) {
+ framework.bind(pswp.scrollWrap, 'mouseover', ui.onMouseOver);
+ }
+ });
+
+ // unbind events for UI
+ _listen('unbindEvents', function() {
+ if(!_shareModalHidden) {
+ _toggleShareModal();
+ }
+
+ if(_idleInterval) {
+ clearInterval(_idleInterval);
+ }
+ framework.unbind(document, 'mouseout', _onMouseLeaveWindow);
+ framework.unbind(document, 'mousemove', _onIdleMouseMove);
+ framework.unbind(_controls, 'pswpTap click', _onControlsTap);
+ framework.unbind(pswp.scrollWrap, 'pswpTap', ui.onGlobalTap);
+ framework.unbind(pswp.scrollWrap, 'mouseover', ui.onMouseOver);
+
+ if(_fullscrenAPI) {
+ framework.unbind(document, _fullscrenAPI.eventK, ui.updateFullscreen);
+ if(_fullscrenAPI.isFullscreen()) {
+ _options.hideAnimationDuration = 0;
+ _fullscrenAPI.exit();
+ }
+ _fullscrenAPI = null;
+ }
+ });
+
+
+ // clean up things when gallery is destroyed
+ _listen('destroy', function() {
+ if(_options.captionEl) {
+ if(_fakeCaptionContainer) {
+ _controls.removeChild(_fakeCaptionContainer);
+ }
+ framework.removeClass(_captionContainer, 'pswp__caption--empty');
+ }
+
+ if(_shareModal) {
+ _shareModal.children[0].onclick = null;
+ }
+ framework.removeClass(_controls, 'pswp__ui--over-close');
+ framework.addClass( _controls, 'pswp__ui--hidden');
+ ui.setIdle(false);
+ });
+
+
+ if(!_options.showAnimationDuration) {
+ framework.removeClass( _controls, 'pswp__ui--hidden');
+ }
+ _listen('initialZoomIn', function() {
+ if(_options.showAnimationDuration) {
+ framework.removeClass( _controls, 'pswp__ui--hidden');
+ }
+ });
+ _listen('initialZoomOut', function() {
+ framework.addClass( _controls, 'pswp__ui--hidden');
+ });
+
+ _listen('parseVerticalMargin', _applyNavBarGaps);
+
+ _setupUIElements();
+
+ if(_options.shareEl && _shareButton && _shareModal) {
+ _shareModalHidden = true;
+ }
+
+ _countNumItems();
+
+ _setupIdle();
+
+ _setupFullscreenAPI();
+
+ _setupLoadingIndicator();
+ };
+
+ ui.setIdle = function(isIdle) {
+ _isIdle = isIdle;
+ _togglePswpClass(_controls, 'ui--idle', isIdle);
+ };
+
+ ui.update = function() {
+ // Don't update UI if it's hidden
+ if(_controlsVisible && pswp.currItem) {
+
+ ui.updateIndexIndicator();
+
+ if(_options.captionEl) {
+ _options.addCaptionHTMLFn(pswp.currItem, _captionContainer);
+
+ _togglePswpClass(_captionContainer, 'caption--empty', !pswp.currItem.title);
+ }
+
+ _overlayUIUpdated = true;
+
+ } else {
+ _overlayUIUpdated = false;
+ }
+
+ if(!_shareModalHidden) {
+ _toggleShareModal();
+ }
+
+ _countNumItems();
+ };
+
+ ui.updateFullscreen = function(e) {
+
+ if(e) {
+ // some browsers change window scroll position during the fullscreen
+ // so PhotoSwipe updates it just in case
+ setTimeout(function() {
+ pswp.setScrollOffset( 0, framework.getScrollY() );
+ }, 50);
+ }
+
+ // toogle pswp--fs class on root element
+ framework[ (_fullscrenAPI.isFullscreen() ? 'add' : 'remove') + 'Class' ](pswp.template, 'pswp--fs');
+ };
+
+ ui.updateIndexIndicator = function() {
+ if(_options.counterEl) {
+ _indexIndicator.innerHTML = (pswp.getCurrentIndex()+1) +
+ _options.indexIndicatorSep +
+ _options.getNumItemsFn();
+ }
+ };
+
+ ui.onGlobalTap = function(e) {
+ e = e || window.event;
+ var target = e.target || e.srcElement;
+
+ if(_blockControlsTap) {
+ return;
+ }
+
+ if(e.detail && e.detail.pointerType === 'mouse') {
+
+ // close gallery if clicked outside of the image
+ if(_hasCloseClass(target)) {
+ pswp.close();
+ return;
+ }
+
+ if(framework.hasClass(target, 'pswp__img')) {
+ if(pswp.getZoomLevel() === 1 && pswp.getZoomLevel() <= pswp.currItem.fitRatio) {
+ if(_options.clickToCloseNonZoomable) {
+ pswp.close();
+ }
+ } else {
+ pswp.toggleDesktopZoom(e.detail.releasePoint);
+ }
+ }
+
+ } else {
+
+ // tap anywhere (except buttons) to toggle visibility of controls
+ if(_options.tapToToggleControls) {
+ if(_controlsVisible) {
+ ui.hideControls();
+ } else {
+ ui.showControls();
+ }
+ }
+
+ // tap to close gallery
+ if(_options.tapToClose && (framework.hasClass(target, 'pswp__img') || _hasCloseClass(target)) ) {
+ pswp.close();
+ return;
+ }
+
+ }
+ };
+ ui.onMouseOver = function(e) {
+ e = e || window.event;
+ var target = e.target || e.srcElement;
+
+ // add class when mouse is over an element that should close the gallery
+ _togglePswpClass(_controls, 'ui--over-close', _hasCloseClass(target));
+ };
+
+ ui.hideControls = function() {
+ framework.addClass(_controls,'pswp__ui--hidden');
+ _controlsVisible = false;
+ };
+
+ ui.showControls = function() {
+ _controlsVisible = true;
+ if(!_overlayUIUpdated) {
+ ui.update();
+ }
+ framework.removeClass(_controls,'pswp__ui--hidden');
+ };
+
+ ui.supportsFullscreen = function() {
+ var d = document;
+ return !!(d.exitFullscreen || d.mozCancelFullScreen || d.webkitExitFullscreen || d.msExitFullscreen);
+ };
+
+ ui.getFullscreenAPI = function() {
+ var dE = document.documentElement,
+ api,
+ tF = 'fullscreenchange';
+
+ if (dE.requestFullscreen) {
+ api = {
+ enterK: 'requestFullscreen',
+ exitK: 'exitFullscreen',
+ elementK: 'fullscreenElement',
+ eventK: tF
+ };
+
+ } else if(dE.mozRequestFullScreen ) {
+ api = {
+ enterK: 'mozRequestFullScreen',
+ exitK: 'mozCancelFullScreen',
+ elementK: 'mozFullScreenElement',
+ eventK: 'moz' + tF
+ };
+
+
+
+ } else if(dE.webkitRequestFullscreen) {
+ api = {
+ enterK: 'webkitRequestFullscreen',
+ exitK: 'webkitExitFullscreen',
+ elementK: 'webkitFullscreenElement',
+ eventK: 'webkit' + tF
+ };
+
+ } else if(dE.msRequestFullscreen) {
+ api = {
+ enterK: 'msRequestFullscreen',
+ exitK: 'msExitFullscreen',
+ elementK: 'msFullscreenElement',
+ eventK: 'MSFullscreenChange'
+ };
+ }
+
+ if(api) {
+ api.enter = function() {
+ // disable close-on-scroll in fullscreen
+ _initalCloseOnScrollValue = _options.closeOnScroll;
+ _options.closeOnScroll = false;
+
+ if(this.enterK === 'webkitRequestFullscreen') {
+ pswp.template[this.enterK]( Element.ALLOW_KEYBOARD_INPUT );
+ } else {
+ return pswp.template[this.enterK]();
+ }
+ };
+ api.exit = function() {
+ _options.closeOnScroll = _initalCloseOnScrollValue;
+
+ return document[this.exitK]();
+
+ };
+ api.isFullscreen = function() { return document[this.elementK]; };
+ }
+
+ return api;
+ };
+
+
+
+};
+return PhotoSwipeUI_Default;
+
+
+});
diff --git a/sigal/themes/photoswipe/static/photoswipe-ui-default.min.js b/sigal/themes/photoswipe/static/photoswipe-ui-default.min.js
index 64b19c3..79115c5 100644
--- a/sigal/themes/photoswipe/static/photoswipe-ui-default.min.js
+++ b/sigal/themes/photoswipe/static/photoswipe-ui-default.min.js
@@ -1,4 +1,4 @@
-/*! PhotoSwipe Default UI - 4.1.1 - 2015-12-24
+/*! PhotoSwipe Default UI - 4.1.2 - 2017-04-05
* http://photoswipe.com
-* Copyright (c) 2015 Dmitry Semenov; */
-!function(a,b){"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():a.PhotoSwipeUI_Default=b()}(this,function(){"use strict";var a=function(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v=this,w=!1,x=!0,y=!0,z={barsSize:{top:44,bottom:"auto"},closeElClasses:["item","caption","zoom-wrap","ui","top-bar"],timeToIdle:4e3,timeToIdleOutside:1e3,loadingIndicatorDelay:1e3,addCaptionHTMLFn:function(a,b){return a.title?(b.children[0].innerHTML=a.title,!0):(b.children[0].innerHTML="",!1)},closeEl:!0,captionEl:!0,fullscreenEl:!0,zoomEl:!0,shareEl:!0,counterEl:!0,arrowEl:!0,preloaderEl:!0,tapToClose:!1,tapToToggleControls:!0,clickToCloseNonZoomable:!0,shareButtons:[{id:"facebook",label:"Share on Facebook",url:"https://www.facebook.com/sharer/sharer.php?u={{url}}"},{id:"twitter",label:"Tweet",url:"https://twitter.com/intent/tweet?text={{text}}&url={{url}}"},{id:"pinterest",label:"Pin it",url:"http://www.pinterest.com/pin/create/button/?url={{url}}&media={{image_url}}&description={{text}}"},{id:"download",label:"Download image",url:"{{raw_image_url}}",download:!0}],getImageURLForShare:function(){return a.currItem.src||""},getPageURLForShare:function(){return window.location.href},getTextForShare:function(){return a.currItem.title||""},indexIndicatorSep:" / ",fitControlsWidth:1200},A=function(a){if(r)return!0;a=a||window.event,q.timeToIdle&&q.mouseUsed&&!k&&K();for(var c,d,e=a.target||a.srcElement,f=e.getAttribute("class")||"",g=0;g
-1&&(c.onTap(),d=!0);if(d){a.stopPropagation&&a.stopPropagation(),r=!0;var h=b.features.isOldAndroid?600:30;s=setTimeout(function(){r=!1},h)}},B=function(){return!a.likelyTouchDevice||q.mouseUsed||screen.width>q.fitControlsWidth},C=function(a,c,d){b[(d?"add":"remove")+"Class"](a,"pswp__"+c)},D=function(){var a=1===q.getNumItemsFn();a!==p&&(C(d,"ui--one-slide",a),p=a)},E=function(){C(i,"share-modal--hidden",y)},F=function(){return y=!y,y?(b.removeClass(i,"pswp__share-modal--fade-in"),setTimeout(function(){y&&E()},300)):(E(),setTimeout(function(){y||b.addClass(i,"pswp__share-modal--fade-in")},30)),y||H(),!1},G=function(b){b=b||window.event;var c=b.target||b.srcElement;return a.shout("shareLinkClick",b,c),c.href?c.hasAttribute("download")?!0:(window.open(c.href,"pswp_share","scrollbars=yes,resizable=yes,toolbar=no,location=yes,width=550,height=420,top=100,left="+(window.screen?Math.round(screen.width/2-275):100)),y||F(),!1):!1},H=function(){for(var a,b,c,d,e,f="",g=0;g"+a.label+"",q.parseShareButtonOut&&(f=q.parseShareButtonOut(a,f));i.children[0].innerHTML=f,i.children[0].onclick=G},I=function(a){for(var c=0;ca?v.hideControls():!x&&a>=.95&&v.showControls()});var a;l("onPinchClose",function(b){x&&.9>b?(v.hideControls(),a=!0):a&&!x&&b>.9&&v.showControls()}),l("zoomGestureEnded",function(){a=!1,a&&!x&&v.showControls()})},S=[{name:"caption",option:"captionEl",onInit:function(a){e=a}},{name:"share-modal",option:"shareEl",onInit:function(a){i=a},onTap:function(){F()}},{name:"button--share",option:"shareEl",onInit:function(a){h=a},onTap:function(){F()}},{name:"button--zoom",option:"zoomEl",onTap:a.toggleDesktopZoom},{name:"counter",option:"counterEl",onInit:function(a){g=a}},{name:"button--close",option:"closeEl",onTap:a.close},{name:"button--arrow--left",option:"arrowEl",onTap:a.prev},{name:"button--arrow--right",option:"arrowEl",onTap:a.next},{name:"button--fs",option:"fullscreenEl",onTap:function(){c.isFullscreen()?c.exit():c.enter()}},{name:"preloader",option:"preloaderEl",onInit:function(a){m=a}}],T=function(){var a,c,e,f=function(d){if(d)for(var f=d.length,g=0;f>g;g++){a=d[g],c=a.className;for(var h=0;h-1&&(q[e.option]?(b.removeClass(a,"pswp__element--disabled"),e.onInit&&e.onInit(a)):b.addClass(a,"pswp__element--disabled"))}};f(d.children);var g=b.getChildByClass(d,"pswp__top-bar");g&&f(g.children)};v.init=function(){b.extend(a.options,z,!0),q=a.options,d=b.getChildByClass(a.scrollWrap,"pswp__ui"),l=a.listen,R(),l("beforeChange",v.update),l("doubleTap",function(b){var c=a.currItem.initialZoomLevel;a.getZoomLevel()!==c?a.zoomTo(c,b,333):a.zoomTo(q.getDoubleTapZoom(!1,a.currItem),b,333)}),l("preventDragEvent",function(a,b,c){var d=a.target||a.srcElement;d&&d.getAttribute("class")&&a.type.indexOf("mouse")>-1&&(d.getAttribute("class").indexOf("__caption")>0||/(SMALL|STRONG|EM)/i.test(d.tagName))&&(c.prevent=!1)}),l("bindEvents",function(){b.bind(d,"pswpTap click",A),b.bind(a.scrollWrap,"pswpTap",v.onGlobalTap),a.likelyTouchDevice||b.bind(a.scrollWrap,"mouseover",v.onMouseOver)}),l("unbindEvents",function(){y||F(),t&&clearInterval(t),b.unbind(document,"mouseout",L),b.unbind(document,"mousemove",K),b.unbind(d,"pswpTap click",A),b.unbind(a.scrollWrap,"pswpTap",v.onGlobalTap),b.unbind(a.scrollWrap,"mouseover",v.onMouseOver),c&&(b.unbind(document,c.eventK,v.updateFullscreen),c.isFullscreen()&&(q.hideAnimationDuration=0,c.exit()),c=null)}),l("destroy",function(){q.captionEl&&(f&&d.removeChild(f),b.removeClass(e,"pswp__caption--empty")),i&&(i.children[0].onclick=null),b.removeClass(d,"pswp__ui--over-close"),b.addClass(d,"pswp__ui--hidden"),v.setIdle(!1)}),q.showAnimationDuration||b.removeClass(d,"pswp__ui--hidden"),l("initialZoomIn",function(){q.showAnimationDuration&&b.removeClass(d,"pswp__ui--hidden")}),l("initialZoomOut",function(){b.addClass(d,"pswp__ui--hidden")}),l("parseVerticalMargin",P),T(),q.shareEl&&h&&i&&(y=!0),D(),Q(),M(),N()},v.setIdle=function(a){k=a,C(d,"ui--idle",a)},v.update=function(){x&&a.currItem?(v.updateIndexIndicator(),q.captionEl&&(q.addCaptionHTMLFn(a.currItem,e),C(e,"caption--empty",!a.currItem.title)),w=!0):w=!1,y||F(),D()},v.updateFullscreen=function(d){d&&setTimeout(function(){a.setScrollOffset(0,b.getScrollY())},50),b[(c.isFullscreen()?"add":"remove")+"Class"](a.template,"pswp--fs")},v.updateIndexIndicator=function(){q.counterEl&&(g.innerHTML=a.getCurrentIndex()+1+q.indexIndicatorSep+q.getNumItemsFn())},v.onGlobalTap=function(c){c=c||window.event;var d=c.target||c.srcElement;if(!r)if(c.detail&&"mouse"===c.detail.pointerType){if(I(d))return void a.close();b.hasClass(d,"pswp__img")&&(1===a.getZoomLevel()&&a.getZoomLevel()<=a.currItem.fitRatio?q.clickToCloseNonZoomable&&a.close():a.toggleDesktopZoom(c.detail.releasePoint))}else if(q.tapToToggleControls&&(x?v.hideControls():v.showControls()),q.tapToClose&&(b.hasClass(d,"pswp__img")||I(d)))return void a.close()},v.onMouseOver=function(a){a=a||window.event;var b=a.target||a.srcElement;C(d,"ui--over-close",I(b))},v.hideControls=function(){b.addClass(d,"pswp__ui--hidden"),x=!1},v.showControls=function(){x=!0,w||v.update(),b.removeClass(d,"pswp__ui--hidden")},v.supportsFullscreen=function(){var a=document;return!!(a.exitFullscreen||a.mozCancelFullScreen||a.webkitExitFullscreen||a.msExitFullscreen)},v.getFullscreenAPI=function(){var b,c=document.documentElement,d="fullscreenchange";return c.requestFullscreen?b={enterK:"requestFullscreen",exitK:"exitFullscreen",elementK:"fullscreenElement",eventK:d}:c.mozRequestFullScreen?b={enterK:"mozRequestFullScreen",exitK:"mozCancelFullScreen",elementK:"mozFullScreenElement",eventK:"moz"+d}:c.webkitRequestFullscreen?b={enterK:"webkitRequestFullscreen",exitK:"webkitExitFullscreen",elementK:"webkitFullscreenElement",eventK:"webkit"+d}:c.msRequestFullscreen&&(b={enterK:"msRequestFullscreen",exitK:"msExitFullscreen",elementK:"msFullscreenElement",eventK:"MSFullscreenChange"}),b&&(b.enter=function(){return j=q.closeOnScroll,q.closeOnScroll=!1,"webkitRequestFullscreen"!==this.enterK?a.template[this.enterK]():void a.template[this.enterK](Element.ALLOW_KEYBOARD_INPUT)},b.exit=function(){return q.closeOnScroll=j,document[this.exitK]()},b.isFullscreen=function(){return document[this.elementK]}),b}};return a});
\ No newline at end of file
+* Copyright (c) 2017 Dmitry Semenov; */
+!function(a,b){"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():a.PhotoSwipeUI_Default=b()}(this,function(){"use strict";var a=function(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v=this,w=!1,x=!0,y=!0,z={barsSize:{top:44,bottom:"auto"},closeElClasses:["item","caption","zoom-wrap","ui","top-bar"],timeToIdle:4e3,timeToIdleOutside:1e3,loadingIndicatorDelay:1e3,addCaptionHTMLFn:function(a,b){return a.title?(b.children[0].innerHTML=a.title,!0):(b.children[0].innerHTML="",!1)},closeEl:!0,captionEl:!0,fullscreenEl:!0,zoomEl:!0,shareEl:!0,counterEl:!0,arrowEl:!0,preloaderEl:!0,tapToClose:!1,tapToToggleControls:!0,clickToCloseNonZoomable:!0,shareButtons:[{id:"facebook",label:"Share on Facebook",url:"https://www.facebook.com/sharer/sharer.php?u={{url}}"},{id:"twitter",label:"Tweet",url:"https://twitter.com/intent/tweet?text={{text}}&url={{url}}"},{id:"pinterest",label:"Pin it",url:"http://www.pinterest.com/pin/create/button/?url={{url}}&media={{image_url}}&description={{text}}"},{id:"download",label:"Download image",url:"{{raw_image_url}}",download:!0}],getImageURLForShare:function(){return a.currItem.src||""},getPageURLForShare:function(){return window.location.href},getTextForShare:function(){return a.currItem.title||""},indexIndicatorSep:" / ",fitControlsWidth:1200},A=function(a){if(r)return!0;a=a||window.event,q.timeToIdle&&q.mouseUsed&&!k&&K();for(var c,d,e=a.target||a.srcElement,f=e.getAttribute("class")||"",g=0;g-1&&(c.onTap(),d=!0);if(d){a.stopPropagation&&a.stopPropagation(),r=!0;var h=b.features.isOldAndroid?600:30;s=setTimeout(function(){r=!1},h)}},B=function(){return!a.likelyTouchDevice||q.mouseUsed||screen.width>q.fitControlsWidth},C=function(a,c,d){b[(d?"add":"remove")+"Class"](a,"pswp__"+c)},D=function(){var a=1===q.getNumItemsFn();a!==p&&(C(d,"ui--one-slide",a),p=a)},E=function(){C(i,"share-modal--hidden",y)},F=function(){return y=!y,y?(b.removeClass(i,"pswp__share-modal--fade-in"),setTimeout(function(){y&&E()},300)):(E(),setTimeout(function(){y||b.addClass(i,"pswp__share-modal--fade-in")},30)),y||H(),!1},G=function(b){b=b||window.event;var c=b.target||b.srcElement;return a.shout("shareLinkClick",b,c),!!c.href&&(!!c.hasAttribute("download")||(window.open(c.href,"pswp_share","scrollbars=yes,resizable=yes,toolbar=no,location=yes,width=550,height=420,top=100,left="+(window.screen?Math.round(screen.width/2-275):100)),y||F(),!1))},H=function(){for(var a,b,c,d,e,f="",g=0;g"+a.label+"",q.parseShareButtonOut&&(f=q.parseShareButtonOut(a,f));i.children[0].innerHTML=f,i.children[0].onclick=G},I=function(a){for(var c=0;c=.95&&v.showControls()});var a;l("onPinchClose",function(b){x&&b<.9?(v.hideControls(),a=!0):a&&!x&&b>.9&&v.showControls()}),l("zoomGestureEnded",function(){a=!1,a&&!x&&v.showControls()})},S=[{name:"caption",option:"captionEl",onInit:function(a){e=a}},{name:"share-modal",option:"shareEl",onInit:function(a){i=a},onTap:function(){F()}},{name:"button--share",option:"shareEl",onInit:function(a){h=a},onTap:function(){F()}},{name:"button--zoom",option:"zoomEl",onTap:a.toggleDesktopZoom},{name:"counter",option:"counterEl",onInit:function(a){g=a}},{name:"button--close",option:"closeEl",onTap:a.close},{name:"button--arrow--left",option:"arrowEl",onTap:a.prev},{name:"button--arrow--right",option:"arrowEl",onTap:a.next},{name:"button--fs",option:"fullscreenEl",onTap:function(){c.isFullscreen()?c.exit():c.enter()}},{name:"preloader",option:"preloaderEl",onInit:function(a){m=a}}],T=function(){var a,c,e,f=function(d){if(d)for(var f=d.length,g=0;g-1&&(q[e.option]?(b.removeClass(a,"pswp__element--disabled"),e.onInit&&e.onInit(a)):b.addClass(a,"pswp__element--disabled"))}};f(d.children);var g=b.getChildByClass(d,"pswp__top-bar");g&&f(g.children)};v.init=function(){b.extend(a.options,z,!0),q=a.options,d=b.getChildByClass(a.scrollWrap,"pswp__ui"),l=a.listen,R(),l("beforeChange",v.update),l("doubleTap",function(b){var c=a.currItem.initialZoomLevel;a.getZoomLevel()!==c?a.zoomTo(c,b,333):a.zoomTo(q.getDoubleTapZoom(!1,a.currItem),b,333)}),l("preventDragEvent",function(a,b,c){var d=a.target||a.srcElement;d&&d.getAttribute("class")&&a.type.indexOf("mouse")>-1&&(d.getAttribute("class").indexOf("__caption")>0||/(SMALL|STRONG|EM)/i.test(d.tagName))&&(c.prevent=!1)}),l("bindEvents",function(){b.bind(d,"pswpTap click",A),b.bind(a.scrollWrap,"pswpTap",v.onGlobalTap),a.likelyTouchDevice||b.bind(a.scrollWrap,"mouseover",v.onMouseOver)}),l("unbindEvents",function(){y||F(),t&&clearInterval(t),b.unbind(document,"mouseout",L),b.unbind(document,"mousemove",K),b.unbind(d,"pswpTap click",A),b.unbind(a.scrollWrap,"pswpTap",v.onGlobalTap),b.unbind(a.scrollWrap,"mouseover",v.onMouseOver),c&&(b.unbind(document,c.eventK,v.updateFullscreen),c.isFullscreen()&&(q.hideAnimationDuration=0,c.exit()),c=null)}),l("destroy",function(){q.captionEl&&(f&&d.removeChild(f),b.removeClass(e,"pswp__caption--empty")),i&&(i.children[0].onclick=null),b.removeClass(d,"pswp__ui--over-close"),b.addClass(d,"pswp__ui--hidden"),v.setIdle(!1)}),q.showAnimationDuration||b.removeClass(d,"pswp__ui--hidden"),l("initialZoomIn",function(){q.showAnimationDuration&&b.removeClass(d,"pswp__ui--hidden")}),l("initialZoomOut",function(){b.addClass(d,"pswp__ui--hidden")}),l("parseVerticalMargin",P),T(),q.shareEl&&h&&i&&(y=!0),D(),Q(),M(),N()},v.setIdle=function(a){k=a,C(d,"ui--idle",a)},v.update=function(){x&&a.currItem?(v.updateIndexIndicator(),q.captionEl&&(q.addCaptionHTMLFn(a.currItem,e),C(e,"caption--empty",!a.currItem.title)),w=!0):w=!1,y||F(),D()},v.updateFullscreen=function(d){d&&setTimeout(function(){a.setScrollOffset(0,b.getScrollY())},50),b[(c.isFullscreen()?"add":"remove")+"Class"](a.template,"pswp--fs")},v.updateIndexIndicator=function(){q.counterEl&&(g.innerHTML=a.getCurrentIndex()+1+q.indexIndicatorSep+q.getNumItemsFn())},v.onGlobalTap=function(c){c=c||window.event;var d=c.target||c.srcElement;if(!r)if(c.detail&&"mouse"===c.detail.pointerType){if(I(d))return void a.close();b.hasClass(d,"pswp__img")&&(1===a.getZoomLevel()&&a.getZoomLevel()<=a.currItem.fitRatio?q.clickToCloseNonZoomable&&a.close():a.toggleDesktopZoom(c.detail.releasePoint))}else if(q.tapToToggleControls&&(x?v.hideControls():v.showControls()),q.tapToClose&&(b.hasClass(d,"pswp__img")||I(d)))return void a.close()},v.onMouseOver=function(a){a=a||window.event;var b=a.target||a.srcElement;C(d,"ui--over-close",I(b))},v.hideControls=function(){b.addClass(d,"pswp__ui--hidden"),x=!1},v.showControls=function(){x=!0,w||v.update(),b.removeClass(d,"pswp__ui--hidden")},v.supportsFullscreen=function(){var a=document;return!!(a.exitFullscreen||a.mozCancelFullScreen||a.webkitExitFullscreen||a.msExitFullscreen)},v.getFullscreenAPI=function(){var b,c=document.documentElement,d="fullscreenchange";return c.requestFullscreen?b={enterK:"requestFullscreen",exitK:"exitFullscreen",elementK:"fullscreenElement",eventK:d}:c.mozRequestFullScreen?b={enterK:"mozRequestFullScreen",exitK:"mozCancelFullScreen",elementK:"mozFullScreenElement",eventK:"moz"+d}:c.webkitRequestFullscreen?b={enterK:"webkitRequestFullscreen",exitK:"webkitExitFullscreen",elementK:"webkitFullscreenElement",eventK:"webkit"+d}:c.msRequestFullscreen&&(b={enterK:"msRequestFullscreen",exitK:"msExitFullscreen",elementK:"msFullscreenElement",eventK:"MSFullscreenChange"}),b&&(b.enter=function(){return j=q.closeOnScroll,q.closeOnScroll=!1,"webkitRequestFullscreen"!==this.enterK?a.template[this.enterK]():void a.template[this.enterK](Element.ALLOW_KEYBOARD_INPUT)},b.exit=function(){return q.closeOnScroll=j,document[this.exitK]()},b.isFullscreen=function(){return document[this.elementK]}),b}};return a});
\ No newline at end of file
diff --git a/sigal/themes/photoswipe/static/photoswipe.css b/sigal/themes/photoswipe/static/photoswipe.css
index 3bf3b40..0ca0f80 100644
--- a/sigal/themes/photoswipe/static/photoswipe.css
+++ b/sigal/themes/photoswipe/static/photoswipe.css
@@ -66,6 +66,8 @@
height: 100%;
background: #000;
opacity: 0;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
-webkit-backface-visibility: hidden;
will-change: opacity; }
diff --git a/sigal/themes/photoswipe/static/photoswipe.js b/sigal/themes/photoswipe/static/photoswipe.js
new file mode 100644
index 0000000..837859f
--- /dev/null
+++ b/sigal/themes/photoswipe/static/photoswipe.js
@@ -0,0 +1,3734 @@
+/*! PhotoSwipe - v4.1.2 - 2017-04-05
+* http://photoswipe.com
+* Copyright (c) 2017 Dmitry Semenov; */
+(function (root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ define(factory);
+ } else if (typeof exports === 'object') {
+ module.exports = factory();
+ } else {
+ root.PhotoSwipe = factory();
+ }
+})(this, function () {
+
+ 'use strict';
+ var PhotoSwipe = function(template, UiClass, items, options){
+
+/*>>framework-bridge*/
+/**
+ *
+ * Set of generic functions used by gallery.
+ *
+ * You're free to modify anything here as long as functionality is kept.
+ *
+ */
+var framework = {
+ features: null,
+ bind: function(target, type, listener, unbind) {
+ var methodName = (unbind ? 'remove' : 'add') + 'EventListener';
+ type = type.split(' ');
+ for(var i = 0; i < type.length; i++) {
+ if(type[i]) {
+ target[methodName]( type[i], listener, false);
+ }
+ }
+ },
+ isArray: function(obj) {
+ return (obj instanceof Array);
+ },
+ createEl: function(classes, tag) {
+ var el = document.createElement(tag || 'div');
+ if(classes) {
+ el.className = classes;
+ }
+ return el;
+ },
+ getScrollY: function() {
+ var yOffset = window.pageYOffset;
+ return yOffset !== undefined ? yOffset : document.documentElement.scrollTop;
+ },
+ unbind: function(target, type, listener) {
+ framework.bind(target,type,listener,true);
+ },
+ removeClass: function(el, className) {
+ var reg = new RegExp('(\\s|^)' + className + '(\\s|$)');
+ el.className = el.className.replace(reg, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+ },
+ addClass: function(el, className) {
+ if( !framework.hasClass(el,className) ) {
+ el.className += (el.className ? ' ' : '') + className;
+ }
+ },
+ hasClass: function(el, className) {
+ return el.className && new RegExp('(^|\\s)' + className + '(\\s|$)').test(el.className);
+ },
+ getChildByClass: function(parentEl, childClassName) {
+ var node = parentEl.firstChild;
+ while(node) {
+ if( framework.hasClass(node, childClassName) ) {
+ return node;
+ }
+ node = node.nextSibling;
+ }
+ },
+ arraySearch: function(array, value, key) {
+ var i = array.length;
+ while(i--) {
+ if(array[i][key] === value) {
+ return i;
+ }
+ }
+ return -1;
+ },
+ extend: function(o1, o2, preventOverwrite) {
+ for (var prop in o2) {
+ if (o2.hasOwnProperty(prop)) {
+ if(preventOverwrite && o1.hasOwnProperty(prop)) {
+ continue;
+ }
+ o1[prop] = o2[prop];
+ }
+ }
+ },
+ easing: {
+ sine: {
+ out: function(k) {
+ return Math.sin(k * (Math.PI / 2));
+ },
+ inOut: function(k) {
+ return - (Math.cos(Math.PI * k) - 1) / 2;
+ }
+ },
+ cubic: {
+ out: function(k) {
+ return --k * k * k + 1;
+ }
+ }
+ /*
+ elastic: {
+ out: function ( k ) {
+
+ var s, a = 0.1, p = 0.4;
+ if ( k === 0 ) return 0;
+ if ( k === 1 ) return 1;
+ if ( !a || a < 1 ) { a = 1; s = p / 4; }
+ else s = p * Math.asin( 1 / a ) / ( 2 * Math.PI );
+ return ( a * Math.pow( 2, - 10 * k) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) + 1 );
+
+ },
+ },
+ back: {
+ out: function ( k ) {
+ var s = 1.70158;
+ return --k * k * ( ( s + 1 ) * k + s ) + 1;
+ }
+ }
+ */
+ },
+
+ /**
+ *
+ * @return {object}
+ *
+ * {
+ * raf : request animation frame function
+ * caf : cancel animation frame function
+ * transfrom : transform property key (with vendor), or null if not supported
+ * oldIE : IE8 or below
+ * }
+ *
+ */
+ detectFeatures: function() {
+ if(framework.features) {
+ return framework.features;
+ }
+ var helperEl = framework.createEl(),
+ helperStyle = helperEl.style,
+ vendor = '',
+ features = {};
+
+ // IE8 and below
+ features.oldIE = document.all && !document.addEventListener;
+
+ features.touch = 'ontouchstart' in window;
+
+ if(window.requestAnimationFrame) {
+ features.raf = window.requestAnimationFrame;
+ features.caf = window.cancelAnimationFrame;
+ }
+
+ features.pointerEvent = navigator.pointerEnabled || navigator.msPointerEnabled;
+
+ // fix false-positive detection of old Android in new IE
+ // (IE11 ua string contains "Android 4.0")
+
+ if(!features.pointerEvent) {
+
+ var ua = navigator.userAgent;
+
+ // Detect if device is iPhone or iPod and if it's older than iOS 8
+ // http://stackoverflow.com/a/14223920
+ //
+ // This detection is made because of buggy top/bottom toolbars
+ // that don't trigger window.resize event.
+ // For more info refer to _isFixedPosition variable in core.js
+
+ if (/iP(hone|od)/.test(navigator.platform)) {
+ var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
+ if(v && v.length > 0) {
+ v = parseInt(v[1], 10);
+ if(v >= 1 && v < 8 ) {
+ features.isOldIOSPhone = true;
+ }
+ }
+ }
+
+ // Detect old Android (before KitKat)
+ // due to bugs related to position:fixed
+ // http://stackoverflow.com/questions/7184573/pick-up-the-android-version-in-the-browser-by-javascript
+
+ var match = ua.match(/Android\s([0-9\.]*)/);
+ var androidversion = match ? match[1] : 0;
+ androidversion = parseFloat(androidversion);
+ if(androidversion >= 1 ) {
+ if(androidversion < 4.4) {
+ features.isOldAndroid = true; // for fixed position bug & performance
+ }
+ features.androidVersion = androidversion; // for touchend bug
+ }
+ features.isMobileOpera = /opera mini|opera mobi/i.test(ua);
+
+ // p.s. yes, yes, UA sniffing is bad, propose your solution for above bugs.
+ }
+
+ var styleChecks = ['transform', 'perspective', 'animationName'],
+ vendors = ['', 'webkit','Moz','ms','O'],
+ styleCheckItem,
+ styleName;
+
+ for(var i = 0; i < 4; i++) {
+ vendor = vendors[i];
+
+ for(var a = 0; a < 3; a++) {
+ styleCheckItem = styleChecks[a];
+
+ // uppercase first letter of property name, if vendor is present
+ styleName = vendor + (vendor ?
+ styleCheckItem.charAt(0).toUpperCase() + styleCheckItem.slice(1) :
+ styleCheckItem);
+
+ if(!features[styleCheckItem] && styleName in helperStyle ) {
+ features[styleCheckItem] = styleName;
+ }
+ }
+
+ if(vendor && !features.raf) {
+ vendor = vendor.toLowerCase();
+ features.raf = window[vendor+'RequestAnimationFrame'];
+ if(features.raf) {
+ features.caf = window[vendor+'CancelAnimationFrame'] ||
+ window[vendor+'CancelRequestAnimationFrame'];
+ }
+ }
+ }
+
+ if(!features.raf) {
+ var lastTime = 0;
+ features.raf = function(fn) {
+ var currTime = new Date().getTime();
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = window.setTimeout(function() { fn(currTime + timeToCall); }, timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+ features.caf = function(id) { clearTimeout(id); };
+ }
+
+ // Detect SVG support
+ features.svg = !!document.createElementNS &&
+ !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect;
+
+ framework.features = features;
+
+ return features;
+ }
+};
+
+framework.detectFeatures();
+
+// Override addEventListener for old versions of IE
+if(framework.features.oldIE) {
+
+ framework.bind = function(target, type, listener, unbind) {
+
+ type = type.split(' ');
+
+ var methodName = (unbind ? 'detach' : 'attach') + 'Event',
+ evName,
+ _handleEv = function() {
+ listener.handleEvent.call(listener);
+ };
+
+ for(var i = 0; i < type.length; i++) {
+ evName = type[i];
+ if(evName) {
+
+ if(typeof listener === 'object' && listener.handleEvent) {
+ if(!unbind) {
+ listener['oldIE' + evName] = _handleEv;
+ } else {
+ if(!listener['oldIE' + evName]) {
+ return false;
+ }
+ }
+
+ target[methodName]( 'on' + evName, listener['oldIE' + evName]);
+ } else {
+ target[methodName]( 'on' + evName, listener);
+ }
+
+ }
+ }
+ };
+
+}
+
+/*>>framework-bridge*/
+
+/*>>core*/
+//function(template, UiClass, items, options)
+
+var self = this;
+
+/**
+ * Static vars, don't change unless you know what you're doing.
+ */
+var DOUBLE_TAP_RADIUS = 25,
+ NUM_HOLDERS = 3;
+
+/**
+ * Options
+ */
+var _options = {
+ allowPanToNext:true,
+ spacing: 0.12,
+ bgOpacity: 1,
+ mouseUsed: false,
+ loop: true,
+ pinchToClose: true,
+ closeOnScroll: true,
+ closeOnVerticalDrag: true,
+ verticalDragRange: 0.75,
+ hideAnimationDuration: 333,
+ showAnimationDuration: 333,
+ showHideOpacity: false,
+ focus: true,
+ escKey: true,
+ arrowKeys: true,
+ mainScrollEndFriction: 0.35,
+ panEndFriction: 0.35,
+ isClickableElement: function(el) {
+ return el.tagName === 'A';
+ },
+ getDoubleTapZoom: function(isMouseClick, item) {
+ if(isMouseClick) {
+ return 1;
+ } else {
+ return item.initialZoomLevel < 0.7 ? 1 : 1.33;
+ }
+ },
+ maxSpreadZoom: 1.33,
+ modal: true,
+
+ // not fully implemented yet
+ scaleMode: 'fit' // TODO
+};
+framework.extend(_options, options);
+
+
+/**
+ * Private helper variables & functions
+ */
+
+var _getEmptyPoint = function() {
+ return {x:0,y:0};
+ };
+
+var _isOpen,
+ _isDestroying,
+ _closedByScroll,
+ _currentItemIndex,
+ _containerStyle,
+ _containerShiftIndex,
+ _currPanDist = _getEmptyPoint(),
+ _startPanOffset = _getEmptyPoint(),
+ _panOffset = _getEmptyPoint(),
+ _upMoveEvents, // drag move, drag end & drag cancel events array
+ _downEvents, // drag start events array
+ _globalEventHandlers,
+ _viewportSize = {},
+ _currZoomLevel,
+ _startZoomLevel,
+ _translatePrefix,
+ _translateSufix,
+ _updateSizeInterval,
+ _itemsNeedUpdate,
+ _currPositionIndex = 0,
+ _offset = {},
+ _slideSize = _getEmptyPoint(), // size of slide area, including spacing
+ _itemHolders,
+ _prevItemIndex,
+ _indexDiff = 0, // difference of indexes since last content update
+ _dragStartEvent,
+ _dragMoveEvent,
+ _dragEndEvent,
+ _dragCancelEvent,
+ _transformKey,
+ _pointerEventEnabled,
+ _isFixedPosition = true,
+ _likelyTouchDevice,
+ _modules = [],
+ _requestAF,
+ _cancelAF,
+ _initalClassName,
+ _initalWindowScrollY,
+ _oldIE,
+ _currentWindowScrollY,
+ _features,
+ _windowVisibleSize = {},
+ _renderMaxResolution = false,
+ _orientationChangeTimeout,
+
+
+ // Registers PhotoSWipe module (History, Controller ...)
+ _registerModule = function(name, module) {
+ framework.extend(self, module.publicMethods);
+ _modules.push(name);
+ },
+
+ _getLoopedId = function(index) {
+ var numSlides = _getNumItems();
+ if(index > numSlides - 1) {
+ return index - numSlides;
+ } else if(index < 0) {
+ return numSlides + index;
+ }
+ return index;
+ },
+
+ // Micro bind/trigger
+ _listeners = {},
+ _listen = function(name, fn) {
+ if(!_listeners[name]) {
+ _listeners[name] = [];
+ }
+ return _listeners[name].push(fn);
+ },
+ _shout = function(name) {
+ var listeners = _listeners[name];
+
+ if(listeners) {
+ var args = Array.prototype.slice.call(arguments);
+ args.shift();
+
+ for(var i = 0; i < listeners.length; i++) {
+ listeners[i].apply(self, args);
+ }
+ }
+ },
+
+ _getCurrentTime = function() {
+ return new Date().getTime();
+ },
+ _applyBgOpacity = function(opacity) {
+ _bgOpacity = opacity;
+ self.bg.style.opacity = opacity * _options.bgOpacity;
+ },
+
+ _applyZoomTransform = function(styleObj,x,y,zoom,item) {
+ if(!_renderMaxResolution || (item && item !== self.currItem) ) {
+ zoom = zoom / (item ? item.fitRatio : self.currItem.fitRatio);
+ }
+
+ styleObj[_transformKey] = _translatePrefix + x + 'px, ' + y + 'px' + _translateSufix + ' scale(' + zoom + ')';
+ },
+ _applyCurrentZoomPan = function( allowRenderResolution ) {
+ if(_currZoomElementStyle) {
+
+ if(allowRenderResolution) {
+ if(_currZoomLevel > self.currItem.fitRatio) {
+ if(!_renderMaxResolution) {
+ _setImageSize(self.currItem, false, true);
+ _renderMaxResolution = true;
+ }
+ } else {
+ if(_renderMaxResolution) {
+ _setImageSize(self.currItem);
+ _renderMaxResolution = false;
+ }
+ }
+ }
+
+
+ _applyZoomTransform(_currZoomElementStyle, _panOffset.x, _panOffset.y, _currZoomLevel);
+ }
+ },
+ _applyZoomPanToItem = function(item) {
+ if(item.container) {
+
+ _applyZoomTransform(item.container.style,
+ item.initialPosition.x,
+ item.initialPosition.y,
+ item.initialZoomLevel,
+ item);
+ }
+ },
+ _setTranslateX = function(x, elStyle) {
+ elStyle[_transformKey] = _translatePrefix + x + 'px, 0px' + _translateSufix;
+ },
+ _moveMainScroll = function(x, dragging) {
+
+ if(!_options.loop && dragging) {
+ var newSlideIndexOffset = _currentItemIndex + (_slideSize.x * _currPositionIndex - x) / _slideSize.x,
+ delta = Math.round(x - _mainScrollPos.x);
+
+ if( (newSlideIndexOffset < 0 && delta > 0) ||
+ (newSlideIndexOffset >= _getNumItems() - 1 && delta < 0) ) {
+ x = _mainScrollPos.x + delta * _options.mainScrollEndFriction;
+ }
+ }
+
+ _mainScrollPos.x = x;
+ _setTranslateX(x, _containerStyle);
+ },
+ _calculatePanOffset = function(axis, zoomLevel) {
+ var m = _midZoomPoint[axis] - _offset[axis];
+ return _startPanOffset[axis] + _currPanDist[axis] + m - m * ( zoomLevel / _startZoomLevel );
+ },
+
+ _equalizePoints = function(p1, p2) {
+ p1.x = p2.x;
+ p1.y = p2.y;
+ if(p2.id) {
+ p1.id = p2.id;
+ }
+ },
+ _roundPoint = function(p) {
+ p.x = Math.round(p.x);
+ p.y = Math.round(p.y);
+ },
+
+ _mouseMoveTimeout = null,
+ _onFirstMouseMove = function() {
+ // Wait until mouse move event is fired at least twice during 100ms
+ // We do this, because some mobile browsers trigger it on touchstart
+ if(_mouseMoveTimeout ) {
+ framework.unbind(document, 'mousemove', _onFirstMouseMove);
+ framework.addClass(template, 'pswp--has_mouse');
+ _options.mouseUsed = true;
+ _shout('mouseUsed');
+ }
+ _mouseMoveTimeout = setTimeout(function() {
+ _mouseMoveTimeout = null;
+ }, 100);
+ },
+
+ _bindEvents = function() {
+ framework.bind(document, 'keydown', self);
+
+ if(_features.transform) {
+ // don't bind click event in browsers that don't support transform (mostly IE8)
+ framework.bind(self.scrollWrap, 'click', self);
+ }
+
+
+ if(!_options.mouseUsed) {
+ framework.bind(document, 'mousemove', _onFirstMouseMove);
+ }
+
+ framework.bind(window, 'resize scroll orientationchange', self);
+
+ _shout('bindEvents');
+ },
+
+ _unbindEvents = function() {
+ framework.unbind(window, 'resize scroll orientationchange', self);
+ framework.unbind(window, 'scroll', _globalEventHandlers.scroll);
+ framework.unbind(document, 'keydown', self);
+ framework.unbind(document, 'mousemove', _onFirstMouseMove);
+
+ if(_features.transform) {
+ framework.unbind(self.scrollWrap, 'click', self);
+ }
+
+ if(_isDragging) {
+ framework.unbind(window, _upMoveEvents, self);
+ }
+
+ clearTimeout(_orientationChangeTimeout);
+
+ _shout('unbindEvents');
+ },
+
+ _calculatePanBounds = function(zoomLevel, update) {
+ var bounds = _calculateItemSize( self.currItem, _viewportSize, zoomLevel );
+ if(update) {
+ _currPanBounds = bounds;
+ }
+ return bounds;
+ },
+
+ _getMinZoomLevel = function(item) {
+ if(!item) {
+ item = self.currItem;
+ }
+ return item.initialZoomLevel;
+ },
+ _getMaxZoomLevel = function(item) {
+ if(!item) {
+ item = self.currItem;
+ }
+ return item.w > 0 ? _options.maxSpreadZoom : 1;
+ },
+
+ // Return true if offset is out of the bounds
+ _modifyDestPanOffset = function(axis, destPanBounds, destPanOffset, destZoomLevel) {
+ if(destZoomLevel === self.currItem.initialZoomLevel) {
+ destPanOffset[axis] = self.currItem.initialPosition[axis];
+ return true;
+ } else {
+ destPanOffset[axis] = _calculatePanOffset(axis, destZoomLevel);
+
+ if(destPanOffset[axis] > destPanBounds.min[axis]) {
+ destPanOffset[axis] = destPanBounds.min[axis];
+ return true;
+ } else if(destPanOffset[axis] < destPanBounds.max[axis] ) {
+ destPanOffset[axis] = destPanBounds.max[axis];
+ return true;
+ }
+ }
+ return false;
+ },
+
+ _setupTransforms = function() {
+
+ if(_transformKey) {
+ // setup 3d transforms
+ var allow3dTransform = _features.perspective && !_likelyTouchDevice;
+ _translatePrefix = 'translate' + (allow3dTransform ? '3d(' : '(');
+ _translateSufix = _features.perspective ? ', 0px)' : ')';
+ return;
+ }
+
+ // Override zoom/pan/move functions in case old browser is used (most likely IE)
+ // (so they use left/top/width/height, instead of CSS transform)
+
+ _transformKey = 'left';
+ framework.addClass(template, 'pswp--ie');
+
+ _setTranslateX = function(x, elStyle) {
+ elStyle.left = x + 'px';
+ };
+ _applyZoomPanToItem = function(item) {
+
+ var zoomRatio = item.fitRatio > 1 ? 1 : item.fitRatio,
+ s = item.container.style,
+ w = zoomRatio * item.w,
+ h = zoomRatio * item.h;
+
+ s.width = w + 'px';
+ s.height = h + 'px';
+ s.left = item.initialPosition.x + 'px';
+ s.top = item.initialPosition.y + 'px';
+
+ };
+ _applyCurrentZoomPan = function() {
+ if(_currZoomElementStyle) {
+
+ var s = _currZoomElementStyle,
+ item = self.currItem,
+ zoomRatio = item.fitRatio > 1 ? 1 : item.fitRatio,
+ w = zoomRatio * item.w,
+ h = zoomRatio * item.h;
+
+ s.width = w + 'px';
+ s.height = h + 'px';
+
+
+ s.left = _panOffset.x + 'px';
+ s.top = _panOffset.y + 'px';
+ }
+
+ };
+ },
+
+ _onKeyDown = function(e) {
+ var keydownAction = '';
+ if(_options.escKey && e.keyCode === 27) {
+ keydownAction = 'close';
+ } else if(_options.arrowKeys) {
+ if(e.keyCode === 37) {
+ keydownAction = 'prev';
+ } else if(e.keyCode === 39) {
+ keydownAction = 'next';
+ }
+ }
+
+ if(keydownAction) {
+ // don't do anything if special key pressed to prevent from overriding default browser actions
+ // e.g. in Chrome on Mac cmd+arrow-left returns to previous page
+ if( !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey ) {
+ if(e.preventDefault) {
+ e.preventDefault();
+ } else {
+ e.returnValue = false;
+ }
+ self[keydownAction]();
+ }
+ }
+ },
+
+ _onGlobalClick = function(e) {
+ if(!e) {
+ return;
+ }
+
+ // don't allow click event to pass through when triggering after drag or some other gesture
+ if(_moved || _zoomStarted || _mainScrollAnimating || _verticalDragInitiated) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ },
+
+ _updatePageScrollOffset = function() {
+ self.setScrollOffset(0, framework.getScrollY());
+ };
+
+
+
+
+
+
+
+// Micro animation engine
+var _animations = {},
+ _numAnimations = 0,
+ _stopAnimation = function(name) {
+ if(_animations[name]) {
+ if(_animations[name].raf) {
+ _cancelAF( _animations[name].raf );
+ }
+ _numAnimations--;
+ delete _animations[name];
+ }
+ },
+ _registerStartAnimation = function(name) {
+ if(_animations[name]) {
+ _stopAnimation(name);
+ }
+ if(!_animations[name]) {
+ _numAnimations++;
+ _animations[name] = {};
+ }
+ },
+ _stopAllAnimations = function() {
+ for (var prop in _animations) {
+
+ if( _animations.hasOwnProperty( prop ) ) {
+ _stopAnimation(prop);
+ }
+
+ }
+ },
+ _animateProp = function(name, b, endProp, d, easingFn, onUpdate, onComplete) {
+ var startAnimTime = _getCurrentTime(), t;
+ _registerStartAnimation(name);
+
+ var animloop = function(){
+ if ( _animations[name] ) {
+
+ t = _getCurrentTime() - startAnimTime; // time diff
+ //b - beginning (start prop)
+ //d - anim duration
+
+ if ( t >= d ) {
+ _stopAnimation(name);
+ onUpdate(endProp);
+ if(onComplete) {
+ onComplete();
+ }
+ return;
+ }
+ onUpdate( (endProp - b) * easingFn(t/d) + b );
+
+ _animations[name].raf = _requestAF(animloop);
+ }
+ };
+ animloop();
+ };
+
+
+
+var publicMethods = {
+
+ // make a few local variables and functions public
+ shout: _shout,
+ listen: _listen,
+ viewportSize: _viewportSize,
+ options: _options,
+
+ isMainScrollAnimating: function() {
+ return _mainScrollAnimating;
+ },
+ getZoomLevel: function() {
+ return _currZoomLevel;
+ },
+ getCurrentIndex: function() {
+ return _currentItemIndex;
+ },
+ isDragging: function() {
+ return _isDragging;
+ },
+ isZooming: function() {
+ return _isZooming;
+ },
+ setScrollOffset: function(x,y) {
+ _offset.x = x;
+ _currentWindowScrollY = _offset.y = y;
+ _shout('updateScrollOffset', _offset);
+ },
+ applyZoomPan: function(zoomLevel,panX,panY,allowRenderResolution) {
+ _panOffset.x = panX;
+ _panOffset.y = panY;
+ _currZoomLevel = zoomLevel;
+ _applyCurrentZoomPan( allowRenderResolution );
+ },
+
+ init: function() {
+
+ if(_isOpen || _isDestroying) {
+ return;
+ }
+
+ var i;
+
+ self.framework = framework; // basic functionality
+ self.template = template; // root DOM element of PhotoSwipe
+ self.bg = framework.getChildByClass(template, 'pswp__bg');
+
+ _initalClassName = template.className;
+ _isOpen = true;
+
+ _features = framework.detectFeatures();
+ _requestAF = _features.raf;
+ _cancelAF = _features.caf;
+ _transformKey = _features.transform;
+ _oldIE = _features.oldIE;
+
+ self.scrollWrap = framework.getChildByClass(template, 'pswp__scroll-wrap');
+ self.container = framework.getChildByClass(self.scrollWrap, 'pswp__container');
+
+ _containerStyle = self.container.style; // for fast access
+
+ // Objects that hold slides (there are only 3 in DOM)
+ self.itemHolders = _itemHolders = [
+ {el:self.container.children[0] , wrap:0, index: -1},
+ {el:self.container.children[1] , wrap:0, index: -1},
+ {el:self.container.children[2] , wrap:0, index: -1}
+ ];
+
+ // hide nearby item holders until initial zoom animation finishes (to avoid extra Paints)
+ _itemHolders[0].el.style.display = _itemHolders[2].el.style.display = 'none';
+
+ _setupTransforms();
+
+ // Setup global events
+ _globalEventHandlers = {
+ resize: self.updateSize,
+
+ // Fixes: iOS 10.3 resize event
+ // does not update scrollWrap.clientWidth instantly after resize
+ // https://github.com/dimsemenov/PhotoSwipe/issues/1315
+ orientationchange: function() {
+ clearTimeout(_orientationChangeTimeout);
+ _orientationChangeTimeout = setTimeout(function() {
+ if(_viewportSize.x !== self.scrollWrap.clientWidth) {
+ self.updateSize();
+ }
+ }, 500);
+ },
+ scroll: _updatePageScrollOffset,
+ keydown: _onKeyDown,
+ click: _onGlobalClick
+ };
+
+ // disable show/hide effects on old browsers that don't support CSS animations or transforms,
+ // old IOS, Android and Opera mobile. Blackberry seems to work fine, even older models.
+ var oldPhone = _features.isOldIOSPhone || _features.isOldAndroid || _features.isMobileOpera;
+ if(!_features.animationName || !_features.transform || oldPhone) {
+ _options.showAnimationDuration = _options.hideAnimationDuration = 0;
+ }
+
+ // init modules
+ for(i = 0; i < _modules.length; i++) {
+ self['init' + _modules[i]]();
+ }
+
+ // init
+ if(UiClass) {
+ var ui = self.ui = new UiClass(self, framework);
+ ui.init();
+ }
+
+ _shout('firstUpdate');
+ _currentItemIndex = _currentItemIndex || _options.index || 0;
+ // validate index
+ if( isNaN(_currentItemIndex) || _currentItemIndex < 0 || _currentItemIndex >= _getNumItems() ) {
+ _currentItemIndex = 0;
+ }
+ self.currItem = _getItemAt( _currentItemIndex );
+
+
+ if(_features.isOldIOSPhone || _features.isOldAndroid) {
+ _isFixedPosition = false;
+ }
+
+ template.setAttribute('aria-hidden', 'false');
+ if(_options.modal) {
+ if(!_isFixedPosition) {
+ template.style.position = 'absolute';
+ template.style.top = framework.getScrollY() + 'px';
+ } else {
+ template.style.position = 'fixed';
+ }
+ }
+
+ if(_currentWindowScrollY === undefined) {
+ _shout('initialLayout');
+ _currentWindowScrollY = _initalWindowScrollY = framework.getScrollY();
+ }
+
+ // add classes to root element of PhotoSwipe
+ var rootClasses = 'pswp--open ';
+ if(_options.mainClass) {
+ rootClasses += _options.mainClass + ' ';
+ }
+ if(_options.showHideOpacity) {
+ rootClasses += 'pswp--animate_opacity ';
+ }
+ rootClasses += _likelyTouchDevice ? 'pswp--touch' : 'pswp--notouch';
+ rootClasses += _features.animationName ? ' pswp--css_animation' : '';
+ rootClasses += _features.svg ? ' pswp--svg' : '';
+ framework.addClass(template, rootClasses);
+
+ self.updateSize();
+
+ // initial update
+ _containerShiftIndex = -1;
+ _indexDiff = null;
+ for(i = 0; i < NUM_HOLDERS; i++) {
+ _setTranslateX( (i+_containerShiftIndex) * _slideSize.x, _itemHolders[i].el.style);
+ }
+
+ if(!_oldIE) {
+ framework.bind(self.scrollWrap, _downEvents, self); // no dragging for old IE
+ }
+
+ _listen('initialZoomInEnd', function() {
+ self.setContent(_itemHolders[0], _currentItemIndex-1);
+ self.setContent(_itemHolders[2], _currentItemIndex+1);
+
+ _itemHolders[0].el.style.display = _itemHolders[2].el.style.display = 'block';
+
+ if(_options.focus) {
+ // focus causes layout,
+ // which causes lag during the animation,
+ // that's why we delay it untill the initial zoom transition ends
+ template.focus();
+ }
+
+
+ _bindEvents();
+ });
+
+ // set content for center slide (first time)
+ self.setContent(_itemHolders[1], _currentItemIndex);
+
+ self.updateCurrItem();
+
+ _shout('afterInit');
+
+ if(!_isFixedPosition) {
+
+ // On all versions of iOS lower than 8.0, we check size of viewport every second.
+ //
+ // This is done to detect when Safari top & bottom bars appear,
+ // as this action doesn't trigger any events (like resize).
+ //
+ // On iOS8 they fixed this.
+ //
+ // 10 Nov 2014: iOS 7 usage ~40%. iOS 8 usage 56%.
+
+ _updateSizeInterval = setInterval(function() {
+ if(!_numAnimations && !_isDragging && !_isZooming && (_currZoomLevel === self.currItem.initialZoomLevel) ) {
+ self.updateSize();
+ }
+ }, 1000);
+ }
+
+ framework.addClass(template, 'pswp--visible');
+ },
+
+ // Close the gallery, then destroy it
+ close: function() {
+ if(!_isOpen) {
+ return;
+ }
+
+ _isOpen = false;
+ _isDestroying = true;
+ _shout('close');
+ _unbindEvents();
+
+ _showOrHide(self.currItem, null, true, self.destroy);
+ },
+
+ // destroys the gallery (unbinds events, cleans up intervals and timeouts to avoid memory leaks)
+ destroy: function() {
+ _shout('destroy');
+
+ if(_showOrHideTimeout) {
+ clearTimeout(_showOrHideTimeout);
+ }
+
+ template.setAttribute('aria-hidden', 'true');
+ template.className = _initalClassName;
+
+ if(_updateSizeInterval) {
+ clearInterval(_updateSizeInterval);
+ }
+
+ framework.unbind(self.scrollWrap, _downEvents, self);
+
+ // we unbind scroll event at the end, as closing animation may depend on it
+ framework.unbind(window, 'scroll', self);
+
+ _stopDragUpdateLoop();
+
+ _stopAllAnimations();
+
+ _listeners = null;
+ },
+
+ /**
+ * Pan image to position
+ * @param {Number} x
+ * @param {Number} y
+ * @param {Boolean} force Will ignore bounds if set to true.
+ */
+ panTo: function(x,y,force) {
+ if(!force) {
+ if(x > _currPanBounds.min.x) {
+ x = _currPanBounds.min.x;
+ } else if(x < _currPanBounds.max.x) {
+ x = _currPanBounds.max.x;
+ }
+
+ if(y > _currPanBounds.min.y) {
+ y = _currPanBounds.min.y;
+ } else if(y < _currPanBounds.max.y) {
+ y = _currPanBounds.max.y;
+ }
+ }
+
+ _panOffset.x = x;
+ _panOffset.y = y;
+ _applyCurrentZoomPan();
+ },
+
+ handleEvent: function (e) {
+ e = e || window.event;
+ if(_globalEventHandlers[e.type]) {
+ _globalEventHandlers[e.type](e);
+ }
+ },
+
+
+ goTo: function(index) {
+
+ index = _getLoopedId(index);
+
+ var diff = index - _currentItemIndex;
+ _indexDiff = diff;
+
+ _currentItemIndex = index;
+ self.currItem = _getItemAt( _currentItemIndex );
+ _currPositionIndex -= diff;
+
+ _moveMainScroll(_slideSize.x * _currPositionIndex);
+
+
+ _stopAllAnimations();
+ _mainScrollAnimating = false;
+
+ self.updateCurrItem();
+ },
+ next: function() {
+ self.goTo( _currentItemIndex + 1);
+ },
+ prev: function() {
+ self.goTo( _currentItemIndex - 1);
+ },
+
+ // update current zoom/pan objects
+ updateCurrZoomItem: function(emulateSetContent) {
+ if(emulateSetContent) {
+ _shout('beforeChange', 0);
+ }
+
+ // itemHolder[1] is middle (current) item
+ if(_itemHolders[1].el.children.length) {
+ var zoomElement = _itemHolders[1].el.children[0];
+ if( framework.hasClass(zoomElement, 'pswp__zoom-wrap') ) {
+ _currZoomElementStyle = zoomElement.style;
+ } else {
+ _currZoomElementStyle = null;
+ }
+ } else {
+ _currZoomElementStyle = null;
+ }
+
+ _currPanBounds = self.currItem.bounds;
+ _startZoomLevel = _currZoomLevel = self.currItem.initialZoomLevel;
+
+ _panOffset.x = _currPanBounds.center.x;
+ _panOffset.y = _currPanBounds.center.y;
+
+ if(emulateSetContent) {
+ _shout('afterChange');
+ }
+ },
+
+
+ invalidateCurrItems: function() {
+ _itemsNeedUpdate = true;
+ for(var i = 0; i < NUM_HOLDERS; i++) {
+ if( _itemHolders[i].item ) {
+ _itemHolders[i].item.needsUpdate = true;
+ }
+ }
+ },
+
+ updateCurrItem: function(beforeAnimation) {
+
+ if(_indexDiff === 0) {
+ return;
+ }
+
+ var diffAbs = Math.abs(_indexDiff),
+ tempHolder;
+
+ if(beforeAnimation && diffAbs < 2) {
+ return;
+ }
+
+
+ self.currItem = _getItemAt( _currentItemIndex );
+ _renderMaxResolution = false;
+
+ _shout('beforeChange', _indexDiff);
+
+ if(diffAbs >= NUM_HOLDERS) {
+ _containerShiftIndex += _indexDiff + (_indexDiff > 0 ? -NUM_HOLDERS : NUM_HOLDERS);
+ diffAbs = NUM_HOLDERS;
+ }
+ for(var i = 0; i < diffAbs; i++) {
+ if(_indexDiff > 0) {
+ tempHolder = _itemHolders.shift();
+ _itemHolders[NUM_HOLDERS-1] = tempHolder; // move first to last
+
+ _containerShiftIndex++;
+ _setTranslateX( (_containerShiftIndex+2) * _slideSize.x, tempHolder.el.style);
+ self.setContent(tempHolder, _currentItemIndex - diffAbs + i + 1 + 1);
+ } else {
+ tempHolder = _itemHolders.pop();
+ _itemHolders.unshift( tempHolder ); // move last to first
+
+ _containerShiftIndex--;
+ _setTranslateX( _containerShiftIndex * _slideSize.x, tempHolder.el.style);
+ self.setContent(tempHolder, _currentItemIndex + diffAbs - i - 1 - 1);
+ }
+
+ }
+
+ // reset zoom/pan on previous item
+ if(_currZoomElementStyle && Math.abs(_indexDiff) === 1) {
+
+ var prevItem = _getItemAt(_prevItemIndex);
+ if(prevItem.initialZoomLevel !== _currZoomLevel) {
+ _calculateItemSize(prevItem , _viewportSize );
+ _setImageSize(prevItem);
+ _applyZoomPanToItem( prevItem );
+ }
+
+ }
+
+ // reset diff after update
+ _indexDiff = 0;
+
+ self.updateCurrZoomItem();
+
+ _prevItemIndex = _currentItemIndex;
+
+ _shout('afterChange');
+
+ },
+
+
+
+ updateSize: function(force) {
+
+ if(!_isFixedPosition && _options.modal) {
+ var windowScrollY = framework.getScrollY();
+ if(_currentWindowScrollY !== windowScrollY) {
+ template.style.top = windowScrollY + 'px';
+ _currentWindowScrollY = windowScrollY;
+ }
+ if(!force && _windowVisibleSize.x === window.innerWidth && _windowVisibleSize.y === window.innerHeight) {
+ return;
+ }
+ _windowVisibleSize.x = window.innerWidth;
+ _windowVisibleSize.y = window.innerHeight;
+
+ //template.style.width = _windowVisibleSize.x + 'px';
+ template.style.height = _windowVisibleSize.y + 'px';
+ }
+
+
+
+ _viewportSize.x = self.scrollWrap.clientWidth;
+ _viewportSize.y = self.scrollWrap.clientHeight;
+
+ _updatePageScrollOffset();
+
+ _slideSize.x = _viewportSize.x + Math.round(_viewportSize.x * _options.spacing);
+ _slideSize.y = _viewportSize.y;
+
+ _moveMainScroll(_slideSize.x * _currPositionIndex);
+
+ _shout('beforeResize'); // even may be used for example to switch image sources
+
+
+ // don't re-calculate size on inital size update
+ if(_containerShiftIndex !== undefined) {
+
+ var holder,
+ item,
+ hIndex;
+
+ for(var i = 0; i < NUM_HOLDERS; i++) {
+ holder = _itemHolders[i];
+ _setTranslateX( (i+_containerShiftIndex) * _slideSize.x, holder.el.style);
+
+ hIndex = _currentItemIndex+i-1;
+
+ if(_options.loop && _getNumItems() > 2) {
+ hIndex = _getLoopedId(hIndex);
+ }
+
+ // update zoom level on items and refresh source (if needsUpdate)
+ item = _getItemAt( hIndex );
+
+ // re-render gallery item if `needsUpdate`,
+ // or doesn't have `bounds` (entirely new slide object)
+ if( item && (_itemsNeedUpdate || item.needsUpdate || !item.bounds) ) {
+
+ self.cleanSlide( item );
+
+ self.setContent( holder, hIndex );
+
+ // if "center" slide
+ if(i === 1) {
+ self.currItem = item;
+ self.updateCurrZoomItem(true);
+ }
+
+ item.needsUpdate = false;
+
+ } else if(holder.index === -1 && hIndex >= 0) {
+ // add content first time
+ self.setContent( holder, hIndex );
+ }
+ if(item && item.container) {
+ _calculateItemSize(item, _viewportSize);
+ _setImageSize(item);
+ _applyZoomPanToItem( item );
+ }
+
+ }
+ _itemsNeedUpdate = false;
+ }
+
+ _startZoomLevel = _currZoomLevel = self.currItem.initialZoomLevel;
+ _currPanBounds = self.currItem.bounds;
+
+ if(_currPanBounds) {
+ _panOffset.x = _currPanBounds.center.x;
+ _panOffset.y = _currPanBounds.center.y;
+ _applyCurrentZoomPan( true );
+ }
+
+ _shout('resize');
+ },
+
+ // Zoom current item to
+ zoomTo: function(destZoomLevel, centerPoint, speed, easingFn, updateFn) {
+ /*
+ if(destZoomLevel === 'fit') {
+ destZoomLevel = self.currItem.fitRatio;
+ } else if(destZoomLevel === 'fill') {
+ destZoomLevel = self.currItem.fillRatio;
+ }
+ */
+
+ if(centerPoint) {
+ _startZoomLevel = _currZoomLevel;
+ _midZoomPoint.x = Math.abs(centerPoint.x) - _panOffset.x ;
+ _midZoomPoint.y = Math.abs(centerPoint.y) - _panOffset.y ;
+ _equalizePoints(_startPanOffset, _panOffset);
+ }
+
+ var destPanBounds = _calculatePanBounds(destZoomLevel, false),
+ destPanOffset = {};
+
+ _modifyDestPanOffset('x', destPanBounds, destPanOffset, destZoomLevel);
+ _modifyDestPanOffset('y', destPanBounds, destPanOffset, destZoomLevel);
+
+ var initialZoomLevel = _currZoomLevel;
+ var initialPanOffset = {
+ x: _panOffset.x,
+ y: _panOffset.y
+ };
+
+ _roundPoint(destPanOffset);
+
+ var onUpdate = function(now) {
+ if(now === 1) {
+ _currZoomLevel = destZoomLevel;
+ _panOffset.x = destPanOffset.x;
+ _panOffset.y = destPanOffset.y;
+ } else {
+ _currZoomLevel = (destZoomLevel - initialZoomLevel) * now + initialZoomLevel;
+ _panOffset.x = (destPanOffset.x - initialPanOffset.x) * now + initialPanOffset.x;
+ _panOffset.y = (destPanOffset.y - initialPanOffset.y) * now + initialPanOffset.y;
+ }
+
+ if(updateFn) {
+ updateFn(now);
+ }
+
+ _applyCurrentZoomPan( now === 1 );
+ };
+
+ if(speed) {
+ _animateProp('customZoomTo', 0, 1, speed, easingFn || framework.easing.sine.inOut, onUpdate);
+ } else {
+ onUpdate(1);
+ }
+ }
+
+
+};
+
+
+/*>>core*/
+
+/*>>gestures*/
+/**
+ * Mouse/touch/pointer event handlers.
+ *
+ * separated from @core.js for readability
+ */
+
+var MIN_SWIPE_DISTANCE = 30,
+ DIRECTION_CHECK_OFFSET = 10; // amount of pixels to drag to determine direction of swipe
+
+var _gestureStartTime,
+ _gestureCheckSpeedTime,
+
+ // pool of objects that are used during dragging of zooming
+ p = {}, // first point
+ p2 = {}, // second point (for zoom gesture)
+ delta = {},
+ _currPoint = {},
+ _startPoint = {},
+ _currPointers = [],
+ _startMainScrollPos = {},
+ _releaseAnimData,
+ _posPoints = [], // array of points during dragging, used to determine type of gesture
+ _tempPoint = {},
+
+ _isZoomingIn,
+ _verticalDragInitiated,
+ _oldAndroidTouchEndTimeout,
+ _currZoomedItemIndex = 0,
+ _centerPoint = _getEmptyPoint(),
+ _lastReleaseTime = 0,
+ _isDragging, // at least one pointer is down
+ _isMultitouch, // at least two _pointers are down
+ _zoomStarted, // zoom level changed during zoom gesture
+ _moved,
+ _dragAnimFrame,
+ _mainScrollShifted,
+ _currentPoints, // array of current touch points
+ _isZooming,
+ _currPointsDistance,
+ _startPointsDistance,
+ _currPanBounds,
+ _mainScrollPos = _getEmptyPoint(),
+ _currZoomElementStyle,
+ _mainScrollAnimating, // true, if animation after swipe gesture is running
+ _midZoomPoint = _getEmptyPoint(),
+ _currCenterPoint = _getEmptyPoint(),
+ _direction,
+ _isFirstMove,
+ _opacityChanged,
+ _bgOpacity,
+ _wasOverInitialZoom,
+
+ _isEqualPoints = function(p1, p2) {
+ return p1.x === p2.x && p1.y === p2.y;
+ },
+ _isNearbyPoints = function(touch0, touch1) {
+ return Math.abs(touch0.x - touch1.x) < DOUBLE_TAP_RADIUS && Math.abs(touch0.y - touch1.y) < DOUBLE_TAP_RADIUS;
+ },
+ _calculatePointsDistance = function(p1, p2) {
+ _tempPoint.x = Math.abs( p1.x - p2.x );
+ _tempPoint.y = Math.abs( p1.y - p2.y );
+ return Math.sqrt(_tempPoint.x * _tempPoint.x + _tempPoint.y * _tempPoint.y);
+ },
+ _stopDragUpdateLoop = function() {
+ if(_dragAnimFrame) {
+ _cancelAF(_dragAnimFrame);
+ _dragAnimFrame = null;
+ }
+ },
+ _dragUpdateLoop = function() {
+ if(_isDragging) {
+ _dragAnimFrame = _requestAF(_dragUpdateLoop);
+ _renderMovement();
+ }
+ },
+ _canPan = function() {
+ return !(_options.scaleMode === 'fit' && _currZoomLevel === self.currItem.initialZoomLevel);
+ },
+
+ // find the closest parent DOM element
+ _closestElement = function(el, fn) {
+ if(!el || el === document) {
+ return false;
+ }
+
+ // don't search elements above pswp__scroll-wrap
+ if(el.getAttribute('class') && el.getAttribute('class').indexOf('pswp__scroll-wrap') > -1 ) {
+ return false;
+ }
+
+ if( fn(el) ) {
+ return el;
+ }
+
+ return _closestElement(el.parentNode, fn);
+ },
+
+ _preventObj = {},
+ _preventDefaultEventBehaviour = function(e, isDown) {
+ _preventObj.prevent = !_closestElement(e.target, _options.isClickableElement);
+
+ _shout('preventDragEvent', e, isDown, _preventObj);
+ return _preventObj.prevent;
+
+ },
+ _convertTouchToPoint = function(touch, p) {
+ p.x = touch.pageX;
+ p.y = touch.pageY;
+ p.id = touch.identifier;
+ return p;
+ },
+ _findCenterOfPoints = function(p1, p2, pCenter) {
+ pCenter.x = (p1.x + p2.x) * 0.5;
+ pCenter.y = (p1.y + p2.y) * 0.5;
+ },
+ _pushPosPoint = function(time, x, y) {
+ if(time - _gestureCheckSpeedTime > 50) {
+ var o = _posPoints.length > 2 ? _posPoints.shift() : {};
+ o.x = x;
+ o.y = y;
+ _posPoints.push(o);
+ _gestureCheckSpeedTime = time;
+ }
+ },
+
+ _calculateVerticalDragOpacityRatio = function() {
+ var yOffset = _panOffset.y - self.currItem.initialPosition.y; // difference between initial and current position
+ return 1 - Math.abs( yOffset / (_viewportSize.y / 2) );
+ },
+
+
+ // points pool, reused during touch events
+ _ePoint1 = {},
+ _ePoint2 = {},
+ _tempPointsArr = [],
+ _tempCounter,
+ _getTouchPoints = function(e) {
+ // clean up previous points, without recreating array
+ while(_tempPointsArr.length > 0) {
+ _tempPointsArr.pop();
+ }
+
+ if(!_pointerEventEnabled) {
+ if(e.type.indexOf('touch') > -1) {
+
+ if(e.touches && e.touches.length > 0) {
+ _tempPointsArr[0] = _convertTouchToPoint(e.touches[0], _ePoint1);
+ if(e.touches.length > 1) {
+ _tempPointsArr[1] = _convertTouchToPoint(e.touches[1], _ePoint2);
+ }
+ }
+
+ } else {
+ _ePoint1.x = e.pageX;
+ _ePoint1.y = e.pageY;
+ _ePoint1.id = '';
+ _tempPointsArr[0] = _ePoint1;//_ePoint1;
+ }
+ } else {
+ _tempCounter = 0;
+ // we can use forEach, as pointer events are supported only in modern browsers
+ _currPointers.forEach(function(p) {
+ if(_tempCounter === 0) {
+ _tempPointsArr[0] = p;
+ } else if(_tempCounter === 1) {
+ _tempPointsArr[1] = p;
+ }
+ _tempCounter++;
+
+ });
+ }
+ return _tempPointsArr;
+ },
+
+ _panOrMoveMainScroll = function(axis, delta) {
+
+ var panFriction,
+ overDiff = 0,
+ newOffset = _panOffset[axis] + delta[axis],
+ startOverDiff,
+ dir = delta[axis] > 0,
+ newMainScrollPosition = _mainScrollPos.x + delta.x,
+ mainScrollDiff = _mainScrollPos.x - _startMainScrollPos.x,
+ newPanPos,
+ newMainScrollPos;
+
+ // calculate fdistance over the bounds and friction
+ if(newOffset > _currPanBounds.min[axis] || newOffset < _currPanBounds.max[axis]) {
+ panFriction = _options.panEndFriction;
+ // Linear increasing of friction, so at 1/4 of viewport it's at max value.
+ // Looks not as nice as was expected. Left for history.
+ // panFriction = (1 - (_panOffset[axis] + delta[axis] + panBounds.min[axis]) / (_viewportSize[axis] / 4) );
+ } else {
+ panFriction = 1;
+ }
+
+ newOffset = _panOffset[axis] + delta[axis] * panFriction;
+
+ // move main scroll or start panning
+ if(_options.allowPanToNext || _currZoomLevel === self.currItem.initialZoomLevel) {
+
+
+ if(!_currZoomElementStyle) {
+
+ newMainScrollPos = newMainScrollPosition;
+
+ } else if(_direction === 'h' && axis === 'x' && !_zoomStarted ) {
+
+ if(dir) {
+ if(newOffset > _currPanBounds.min[axis]) {
+ panFriction = _options.panEndFriction;
+ overDiff = _currPanBounds.min[axis] - newOffset;
+ startOverDiff = _currPanBounds.min[axis] - _startPanOffset[axis];
+ }
+
+ // drag right
+ if( (startOverDiff <= 0 || mainScrollDiff < 0) && _getNumItems() > 1 ) {
+ newMainScrollPos = newMainScrollPosition;
+ if(mainScrollDiff < 0 && newMainScrollPosition > _startMainScrollPos.x) {
+ newMainScrollPos = _startMainScrollPos.x;
+ }
+ } else {
+ if(_currPanBounds.min.x !== _currPanBounds.max.x) {
+ newPanPos = newOffset;
+ }
+
+ }
+
+ } else {
+
+ if(newOffset < _currPanBounds.max[axis] ) {
+ panFriction =_options.panEndFriction;
+ overDiff = newOffset - _currPanBounds.max[axis];
+ startOverDiff = _startPanOffset[axis] - _currPanBounds.max[axis];
+ }
+
+ if( (startOverDiff <= 0 || mainScrollDiff > 0) && _getNumItems() > 1 ) {
+ newMainScrollPos = newMainScrollPosition;
+
+ if(mainScrollDiff > 0 && newMainScrollPosition < _startMainScrollPos.x) {
+ newMainScrollPos = _startMainScrollPos.x;
+ }
+
+ } else {
+ if(_currPanBounds.min.x !== _currPanBounds.max.x) {
+ newPanPos = newOffset;
+ }
+ }
+
+ }
+
+
+ //
+ }
+
+ if(axis === 'x') {
+
+ if(newMainScrollPos !== undefined) {
+ _moveMainScroll(newMainScrollPos, true);
+ if(newMainScrollPos === _startMainScrollPos.x) {
+ _mainScrollShifted = false;
+ } else {
+ _mainScrollShifted = true;
+ }
+ }
+
+ if(_currPanBounds.min.x !== _currPanBounds.max.x) {
+ if(newPanPos !== undefined) {
+ _panOffset.x = newPanPos;
+ } else if(!_mainScrollShifted) {
+ _panOffset.x += delta.x * panFriction;
+ }
+ }
+
+ return newMainScrollPos !== undefined;
+ }
+
+ }
+
+ if(!_mainScrollAnimating) {
+
+ if(!_mainScrollShifted) {
+ if(_currZoomLevel > self.currItem.fitRatio) {
+ _panOffset[axis] += delta[axis] * panFriction;
+
+ }
+ }
+
+
+ }
+
+ },
+
+ // Pointerdown/touchstart/mousedown handler
+ _onDragStart = function(e) {
+
+ // Allow dragging only via left mouse button.
+ // As this handler is not added in IE8 - we ignore e.which
+ //
+ // http://www.quirksmode.org/js/events_properties.html
+ // https://developer.mozilla.org/en-US/docs/Web/API/event.button
+ if(e.type === 'mousedown' && e.button > 0 ) {
+ return;
+ }
+
+ if(_initialZoomRunning) {
+ e.preventDefault();
+ return;
+ }
+
+ if(_oldAndroidTouchEndTimeout && e.type === 'mousedown') {
+ return;
+ }
+
+ if(_preventDefaultEventBehaviour(e, true)) {
+ e.preventDefault();
+ }
+
+
+
+ _shout('pointerDown');
+
+ if(_pointerEventEnabled) {
+ var pointerIndex = framework.arraySearch(_currPointers, e.pointerId, 'id');
+ if(pointerIndex < 0) {
+ pointerIndex = _currPointers.length;
+ }
+ _currPointers[pointerIndex] = {x:e.pageX, y:e.pageY, id: e.pointerId};
+ }
+
+
+
+ var startPointsList = _getTouchPoints(e),
+ numPoints = startPointsList.length;
+
+ _currentPoints = null;
+
+ _stopAllAnimations();
+
+ // init drag
+ if(!_isDragging || numPoints === 1) {
+
+
+
+ _isDragging = _isFirstMove = true;
+ framework.bind(window, _upMoveEvents, self);
+
+ _isZoomingIn =
+ _wasOverInitialZoom =
+ _opacityChanged =
+ _verticalDragInitiated =
+ _mainScrollShifted =
+ _moved =
+ _isMultitouch =
+ _zoomStarted = false;
+
+ _direction = null;
+
+ _shout('firstTouchStart', startPointsList);
+
+ _equalizePoints(_startPanOffset, _panOffset);
+
+ _currPanDist.x = _currPanDist.y = 0;
+ _equalizePoints(_currPoint, startPointsList[0]);
+ _equalizePoints(_startPoint, _currPoint);
+
+ //_equalizePoints(_startMainScrollPos, _mainScrollPos);
+ _startMainScrollPos.x = _slideSize.x * _currPositionIndex;
+
+ _posPoints = [{
+ x: _currPoint.x,
+ y: _currPoint.y
+ }];
+
+ _gestureCheckSpeedTime = _gestureStartTime = _getCurrentTime();
+
+ //_mainScrollAnimationEnd(true);
+ _calculatePanBounds( _currZoomLevel, true );
+
+ // Start rendering
+ _stopDragUpdateLoop();
+ _dragUpdateLoop();
+
+ }
+
+ // init zoom
+ if(!_isZooming && numPoints > 1 && !_mainScrollAnimating && !_mainScrollShifted) {
+ _startZoomLevel = _currZoomLevel;
+ _zoomStarted = false; // true if zoom changed at least once
+
+ _isZooming = _isMultitouch = true;
+ _currPanDist.y = _currPanDist.x = 0;
+
+ _equalizePoints(_startPanOffset, _panOffset);
+
+ _equalizePoints(p, startPointsList[0]);
+ _equalizePoints(p2, startPointsList[1]);
+
+ _findCenterOfPoints(p, p2, _currCenterPoint);
+
+ _midZoomPoint.x = Math.abs(_currCenterPoint.x) - _panOffset.x;
+ _midZoomPoint.y = Math.abs(_currCenterPoint.y) - _panOffset.y;
+ _currPointsDistance = _startPointsDistance = _calculatePointsDistance(p, p2);
+ }
+
+
+ },
+
+ // Pointermove/touchmove/mousemove handler
+ _onDragMove = function(e) {
+
+ e.preventDefault();
+
+ if(_pointerEventEnabled) {
+ var pointerIndex = framework.arraySearch(_currPointers, e.pointerId, 'id');
+ if(pointerIndex > -1) {
+ var p = _currPointers[pointerIndex];
+ p.x = e.pageX;
+ p.y = e.pageY;
+ }
+ }
+
+ if(_isDragging) {
+ var touchesList = _getTouchPoints(e);
+ if(!_direction && !_moved && !_isZooming) {
+
+ if(_mainScrollPos.x !== _slideSize.x * _currPositionIndex) {
+ // if main scroll position is shifted – direction is always horizontal
+ _direction = 'h';
+ } else {
+ var diff = Math.abs(touchesList[0].x - _currPoint.x) - Math.abs(touchesList[0].y - _currPoint.y);
+ // check the direction of movement
+ if(Math.abs(diff) >= DIRECTION_CHECK_OFFSET) {
+ _direction = diff > 0 ? 'h' : 'v';
+ _currentPoints = touchesList;
+ }
+ }
+
+ } else {
+ _currentPoints = touchesList;
+ }
+ }
+ },
+ //
+ _renderMovement = function() {
+
+ if(!_currentPoints) {
+ return;
+ }
+
+ var numPoints = _currentPoints.length;
+
+ if(numPoints === 0) {
+ return;
+ }
+
+ _equalizePoints(p, _currentPoints[0]);
+
+ delta.x = p.x - _currPoint.x;
+ delta.y = p.y - _currPoint.y;
+
+ if(_isZooming && numPoints > 1) {
+ // Handle behaviour for more than 1 point
+
+ _currPoint.x = p.x;
+ _currPoint.y = p.y;
+
+ // check if one of two points changed
+ if( !delta.x && !delta.y && _isEqualPoints(_currentPoints[1], p2) ) {
+ return;
+ }
+
+ _equalizePoints(p2, _currentPoints[1]);
+
+
+ if(!_zoomStarted) {
+ _zoomStarted = true;
+ _shout('zoomGestureStarted');
+ }
+
+ // Distance between two points
+ var pointsDistance = _calculatePointsDistance(p,p2);
+
+ var zoomLevel = _calculateZoomLevel(pointsDistance);
+
+ // slightly over the of initial zoom level
+ if(zoomLevel > self.currItem.initialZoomLevel + self.currItem.initialZoomLevel / 15) {
+ _wasOverInitialZoom = true;
+ }
+
+ // Apply the friction if zoom level is out of the bounds
+ var zoomFriction = 1,
+ minZoomLevel = _getMinZoomLevel(),
+ maxZoomLevel = _getMaxZoomLevel();
+
+ if ( zoomLevel < minZoomLevel ) {
+
+ if(_options.pinchToClose && !_wasOverInitialZoom && _startZoomLevel <= self.currItem.initialZoomLevel) {
+ // fade out background if zooming out
+ var minusDiff = minZoomLevel - zoomLevel;
+ var percent = 1 - minusDiff / (minZoomLevel / 1.2);
+
+ _applyBgOpacity(percent);
+ _shout('onPinchClose', percent);
+ _opacityChanged = true;
+ } else {
+ zoomFriction = (minZoomLevel - zoomLevel) / minZoomLevel;
+ if(zoomFriction > 1) {
+ zoomFriction = 1;
+ }
+ zoomLevel = minZoomLevel - zoomFriction * (minZoomLevel / 3);
+ }
+
+ } else if ( zoomLevel > maxZoomLevel ) {
+ // 1.5 - extra zoom level above the max. E.g. if max is x6, real max 6 + 1.5 = 7.5
+ zoomFriction = (zoomLevel - maxZoomLevel) / ( minZoomLevel * 6 );
+ if(zoomFriction > 1) {
+ zoomFriction = 1;
+ }
+ zoomLevel = maxZoomLevel + zoomFriction * minZoomLevel;
+ }
+
+ if(zoomFriction < 0) {
+ zoomFriction = 0;
+ }
+
+ // distance between touch points after friction is applied
+ _currPointsDistance = pointsDistance;
+
+ // _centerPoint - The point in the middle of two pointers
+ _findCenterOfPoints(p, p2, _centerPoint);
+
+ // paning with two pointers pressed
+ _currPanDist.x += _centerPoint.x - _currCenterPoint.x;
+ _currPanDist.y += _centerPoint.y - _currCenterPoint.y;
+ _equalizePoints(_currCenterPoint, _centerPoint);
+
+ _panOffset.x = _calculatePanOffset('x', zoomLevel);
+ _panOffset.y = _calculatePanOffset('y', zoomLevel);
+
+ _isZoomingIn = zoomLevel > _currZoomLevel;
+ _currZoomLevel = zoomLevel;
+ _applyCurrentZoomPan();
+
+ } else {
+
+ // handle behaviour for one point (dragging or panning)
+
+ if(!_direction) {
+ return;
+ }
+
+ if(_isFirstMove) {
+ _isFirstMove = false;
+
+ // subtract drag distance that was used during the detection direction
+
+ if( Math.abs(delta.x) >= DIRECTION_CHECK_OFFSET) {
+ delta.x -= _currentPoints[0].x - _startPoint.x;
+ }
+
+ if( Math.abs(delta.y) >= DIRECTION_CHECK_OFFSET) {
+ delta.y -= _currentPoints[0].y - _startPoint.y;
+ }
+ }
+
+ _currPoint.x = p.x;
+ _currPoint.y = p.y;
+
+ // do nothing if pointers position hasn't changed
+ if(delta.x === 0 && delta.y === 0) {
+ return;
+ }
+
+ if(_direction === 'v' && _options.closeOnVerticalDrag) {
+ if(!_canPan()) {
+ _currPanDist.y += delta.y;
+ _panOffset.y += delta.y;
+
+ var opacityRatio = _calculateVerticalDragOpacityRatio();
+
+ _verticalDragInitiated = true;
+ _shout('onVerticalDrag', opacityRatio);
+
+ _applyBgOpacity(opacityRatio);
+ _applyCurrentZoomPan();
+ return ;
+ }
+ }
+
+ _pushPosPoint(_getCurrentTime(), p.x, p.y);
+
+ _moved = true;
+ _currPanBounds = self.currItem.bounds;
+
+ var mainScrollChanged = _panOrMoveMainScroll('x', delta);
+ if(!mainScrollChanged) {
+ _panOrMoveMainScroll('y', delta);
+
+ _roundPoint(_panOffset);
+ _applyCurrentZoomPan();
+ }
+
+ }
+
+ },
+
+ // Pointerup/pointercancel/touchend/touchcancel/mouseup event handler
+ _onDragRelease = function(e) {
+
+ if(_features.isOldAndroid ) {
+
+ if(_oldAndroidTouchEndTimeout && e.type === 'mouseup') {
+ return;
+ }
+
+ // on Android (v4.1, 4.2, 4.3 & possibly older)
+ // ghost mousedown/up event isn't preventable via e.preventDefault,
+ // which causes fake mousedown event
+ // so we block mousedown/up for 600ms
+ if( e.type.indexOf('touch') > -1 ) {
+ clearTimeout(_oldAndroidTouchEndTimeout);
+ _oldAndroidTouchEndTimeout = setTimeout(function() {
+ _oldAndroidTouchEndTimeout = 0;
+ }, 600);
+ }
+
+ }
+
+ _shout('pointerUp');
+
+ if(_preventDefaultEventBehaviour(e, false)) {
+ e.preventDefault();
+ }
+
+ var releasePoint;
+
+ if(_pointerEventEnabled) {
+ var pointerIndex = framework.arraySearch(_currPointers, e.pointerId, 'id');
+
+ if(pointerIndex > -1) {
+ releasePoint = _currPointers.splice(pointerIndex, 1)[0];
+
+ if(navigator.pointerEnabled) {
+ releasePoint.type = e.pointerType || 'mouse';
+ } else {
+ var MSPOINTER_TYPES = {
+ 4: 'mouse', // event.MSPOINTER_TYPE_MOUSE
+ 2: 'touch', // event.MSPOINTER_TYPE_TOUCH
+ 3: 'pen' // event.MSPOINTER_TYPE_PEN
+ };
+ releasePoint.type = MSPOINTER_TYPES[e.pointerType];
+
+ if(!releasePoint.type) {
+ releasePoint.type = e.pointerType || 'mouse';
+ }
+ }
+
+ }
+ }
+
+ var touchList = _getTouchPoints(e),
+ gestureType,
+ numPoints = touchList.length;
+
+ if(e.type === 'mouseup') {
+ numPoints = 0;
+ }
+
+ // Do nothing if there were 3 touch points or more
+ if(numPoints === 2) {
+ _currentPoints = null;
+ return true;
+ }
+
+ // if second pointer released
+ if(numPoints === 1) {
+ _equalizePoints(_startPoint, touchList[0]);
+ }
+
+
+ // pointer hasn't moved, send "tap release" point
+ if(numPoints === 0 && !_direction && !_mainScrollAnimating) {
+ if(!releasePoint) {
+ if(e.type === 'mouseup') {
+ releasePoint = {x: e.pageX, y: e.pageY, type:'mouse'};
+ } else if(e.changedTouches && e.changedTouches[0]) {
+ releasePoint = {x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY, type:'touch'};
+ }
+ }
+
+ _shout('touchRelease', e, releasePoint);
+ }
+
+ // Difference in time between releasing of two last touch points (zoom gesture)
+ var releaseTimeDiff = -1;
+
+ // Gesture completed, no pointers left
+ if(numPoints === 0) {
+ _isDragging = false;
+ framework.unbind(window, _upMoveEvents, self);
+
+ _stopDragUpdateLoop();
+
+ if(_isZooming) {
+ // Two points released at the same time
+ releaseTimeDiff = 0;
+ } else if(_lastReleaseTime !== -1) {
+ releaseTimeDiff = _getCurrentTime() - _lastReleaseTime;
+ }
+ }
+ _lastReleaseTime = numPoints === 1 ? _getCurrentTime() : -1;
+
+ if(releaseTimeDiff !== -1 && releaseTimeDiff < 150) {
+ gestureType = 'zoom';
+ } else {
+ gestureType = 'swipe';
+ }
+
+ if(_isZooming && numPoints < 2) {
+ _isZooming = false;
+
+ // Only second point released
+ if(numPoints === 1) {
+ gestureType = 'zoomPointerUp';
+ }
+ _shout('zoomGestureEnded');
+ }
+
+ _currentPoints = null;
+ if(!_moved && !_zoomStarted && !_mainScrollAnimating && !_verticalDragInitiated) {
+ // nothing to animate
+ return;
+ }
+
+ _stopAllAnimations();
+
+
+ if(!_releaseAnimData) {
+ _releaseAnimData = _initDragReleaseAnimationData();
+ }
+
+ _releaseAnimData.calculateSwipeSpeed('x');
+
+
+ if(_verticalDragInitiated) {
+
+ var opacityRatio = _calculateVerticalDragOpacityRatio();
+
+ if(opacityRatio < _options.verticalDragRange) {
+ self.close();
+ } else {
+ var initalPanY = _panOffset.y,
+ initialBgOpacity = _bgOpacity;
+
+ _animateProp('verticalDrag', 0, 1, 300, framework.easing.cubic.out, function(now) {
+
+ _panOffset.y = (self.currItem.initialPosition.y - initalPanY) * now + initalPanY;
+
+ _applyBgOpacity( (1 - initialBgOpacity) * now + initialBgOpacity );
+ _applyCurrentZoomPan();
+ });
+
+ _shout('onVerticalDrag', 1);
+ }
+
+ return;
+ }
+
+
+ // main scroll
+ if( (_mainScrollShifted || _mainScrollAnimating) && numPoints === 0) {
+ var itemChanged = _finishSwipeMainScrollGesture(gestureType, _releaseAnimData);
+ if(itemChanged) {
+ return;
+ }
+ gestureType = 'zoomPointerUp';
+ }
+
+ // prevent zoom/pan animation when main scroll animation runs
+ if(_mainScrollAnimating) {
+ return;
+ }
+
+ // Complete simple zoom gesture (reset zoom level if it's out of the bounds)
+ if(gestureType !== 'swipe') {
+ _completeZoomGesture();
+ return;
+ }
+
+ // Complete pan gesture if main scroll is not shifted, and it's possible to pan current image
+ if(!_mainScrollShifted && _currZoomLevel > self.currItem.fitRatio) {
+ _completePanGesture(_releaseAnimData);
+ }
+ },
+
+
+ // Returns object with data about gesture
+ // It's created only once and then reused
+ _initDragReleaseAnimationData = function() {
+ // temp local vars
+ var lastFlickDuration,
+ tempReleasePos;
+
+ // s = this
+ var s = {
+ lastFlickOffset: {},
+ lastFlickDist: {},
+ lastFlickSpeed: {},
+ slowDownRatio: {},
+ slowDownRatioReverse: {},
+ speedDecelerationRatio: {},
+ speedDecelerationRatioAbs: {},
+ distanceOffset: {},
+ backAnimDestination: {},
+ backAnimStarted: {},
+ calculateSwipeSpeed: function(axis) {
+
+
+ if( _posPoints.length > 1) {
+ lastFlickDuration = _getCurrentTime() - _gestureCheckSpeedTime + 50;
+ tempReleasePos = _posPoints[_posPoints.length-2][axis];
+ } else {
+ lastFlickDuration = _getCurrentTime() - _gestureStartTime; // total gesture duration
+ tempReleasePos = _startPoint[axis];
+ }
+ s.lastFlickOffset[axis] = _currPoint[axis] - tempReleasePos;
+ s.lastFlickDist[axis] = Math.abs(s.lastFlickOffset[axis]);
+ if(s.lastFlickDist[axis] > 20) {
+ s.lastFlickSpeed[axis] = s.lastFlickOffset[axis] / lastFlickDuration;
+ } else {
+ s.lastFlickSpeed[axis] = 0;
+ }
+ if( Math.abs(s.lastFlickSpeed[axis]) < 0.1 ) {
+ s.lastFlickSpeed[axis] = 0;
+ }
+
+ s.slowDownRatio[axis] = 0.95;
+ s.slowDownRatioReverse[axis] = 1 - s.slowDownRatio[axis];
+ s.speedDecelerationRatio[axis] = 1;
+ },
+
+ calculateOverBoundsAnimOffset: function(axis, speed) {
+ if(!s.backAnimStarted[axis]) {
+
+ if(_panOffset[axis] > _currPanBounds.min[axis]) {
+ s.backAnimDestination[axis] = _currPanBounds.min[axis];
+
+ } else if(_panOffset[axis] < _currPanBounds.max[axis]) {
+ s.backAnimDestination[axis] = _currPanBounds.max[axis];
+ }
+
+ if(s.backAnimDestination[axis] !== undefined) {
+ s.slowDownRatio[axis] = 0.7;
+ s.slowDownRatioReverse[axis] = 1 - s.slowDownRatio[axis];
+ if(s.speedDecelerationRatioAbs[axis] < 0.05) {
+
+ s.lastFlickSpeed[axis] = 0;
+ s.backAnimStarted[axis] = true;
+
+ _animateProp('bounceZoomPan'+axis,_panOffset[axis],
+ s.backAnimDestination[axis],
+ speed || 300,
+ framework.easing.sine.out,
+ function(pos) {
+ _panOffset[axis] = pos;
+ _applyCurrentZoomPan();
+ }
+ );
+
+ }
+ }
+ }
+ },
+
+ // Reduces the speed by slowDownRatio (per 10ms)
+ calculateAnimOffset: function(axis) {
+ if(!s.backAnimStarted[axis]) {
+ s.speedDecelerationRatio[axis] = s.speedDecelerationRatio[axis] * (s.slowDownRatio[axis] +
+ s.slowDownRatioReverse[axis] -
+ s.slowDownRatioReverse[axis] * s.timeDiff / 10);
+
+ s.speedDecelerationRatioAbs[axis] = Math.abs(s.lastFlickSpeed[axis] * s.speedDecelerationRatio[axis]);
+ s.distanceOffset[axis] = s.lastFlickSpeed[axis] * s.speedDecelerationRatio[axis] * s.timeDiff;
+ _panOffset[axis] += s.distanceOffset[axis];
+
+ }
+ },
+
+ panAnimLoop: function() {
+ if ( _animations.zoomPan ) {
+ _animations.zoomPan.raf = _requestAF(s.panAnimLoop);
+
+ s.now = _getCurrentTime();
+ s.timeDiff = s.now - s.lastNow;
+ s.lastNow = s.now;
+
+ s.calculateAnimOffset('x');
+ s.calculateAnimOffset('y');
+
+ _applyCurrentZoomPan();
+
+ s.calculateOverBoundsAnimOffset('x');
+ s.calculateOverBoundsAnimOffset('y');
+
+
+ if (s.speedDecelerationRatioAbs.x < 0.05 && s.speedDecelerationRatioAbs.y < 0.05) {
+
+ // round pan position
+ _panOffset.x = Math.round(_panOffset.x);
+ _panOffset.y = Math.round(_panOffset.y);
+ _applyCurrentZoomPan();
+
+ _stopAnimation('zoomPan');
+ return;
+ }
+ }
+
+ }
+ };
+ return s;
+ },
+
+ _completePanGesture = function(animData) {
+ // calculate swipe speed for Y axis (paanning)
+ animData.calculateSwipeSpeed('y');
+
+ _currPanBounds = self.currItem.bounds;
+
+ animData.backAnimDestination = {};
+ animData.backAnimStarted = {};
+
+ // Avoid acceleration animation if speed is too low
+ if(Math.abs(animData.lastFlickSpeed.x) <= 0.05 && Math.abs(animData.lastFlickSpeed.y) <= 0.05 ) {
+ animData.speedDecelerationRatioAbs.x = animData.speedDecelerationRatioAbs.y = 0;
+
+ // Run pan drag release animation. E.g. if you drag image and release finger without momentum.
+ animData.calculateOverBoundsAnimOffset('x');
+ animData.calculateOverBoundsAnimOffset('y');
+ return true;
+ }
+
+ // Animation loop that controls the acceleration after pan gesture ends
+ _registerStartAnimation('zoomPan');
+ animData.lastNow = _getCurrentTime();
+ animData.panAnimLoop();
+ },
+
+
+ _finishSwipeMainScrollGesture = function(gestureType, _releaseAnimData) {
+ var itemChanged;
+ if(!_mainScrollAnimating) {
+ _currZoomedItemIndex = _currentItemIndex;
+ }
+
+
+
+ var itemsDiff;
+
+ if(gestureType === 'swipe') {
+ var totalShiftDist = _currPoint.x - _startPoint.x,
+ isFastLastFlick = _releaseAnimData.lastFlickDist.x < 10;
+
+ // if container is shifted for more than MIN_SWIPE_DISTANCE,
+ // and last flick gesture was in right direction
+ if(totalShiftDist > MIN_SWIPE_DISTANCE &&
+ (isFastLastFlick || _releaseAnimData.lastFlickOffset.x > 20) ) {
+ // go to prev item
+ itemsDiff = -1;
+ } else if(totalShiftDist < -MIN_SWIPE_DISTANCE &&
+ (isFastLastFlick || _releaseAnimData.lastFlickOffset.x < -20) ) {
+ // go to next item
+ itemsDiff = 1;
+ }
+ }
+
+ var nextCircle;
+
+ if(itemsDiff) {
+
+ _currentItemIndex += itemsDiff;
+
+ if(_currentItemIndex < 0) {
+ _currentItemIndex = _options.loop ? _getNumItems()-1 : 0;
+ nextCircle = true;
+ } else if(_currentItemIndex >= _getNumItems()) {
+ _currentItemIndex = _options.loop ? 0 : _getNumItems()-1;
+ nextCircle = true;
+ }
+
+ if(!nextCircle || _options.loop) {
+ _indexDiff += itemsDiff;
+ _currPositionIndex -= itemsDiff;
+ itemChanged = true;
+ }
+
+
+
+ }
+
+ var animateToX = _slideSize.x * _currPositionIndex;
+ var animateToDist = Math.abs( animateToX - _mainScrollPos.x );
+ var finishAnimDuration;
+
+
+ if(!itemChanged && animateToX > _mainScrollPos.x !== _releaseAnimData.lastFlickSpeed.x > 0) {
+ // "return to current" duration, e.g. when dragging from slide 0 to -1
+ finishAnimDuration = 333;
+ } else {
+ finishAnimDuration = Math.abs(_releaseAnimData.lastFlickSpeed.x) > 0 ?
+ animateToDist / Math.abs(_releaseAnimData.lastFlickSpeed.x) :
+ 333;
+
+ finishAnimDuration = Math.min(finishAnimDuration, 400);
+ finishAnimDuration = Math.max(finishAnimDuration, 250);
+ }
+
+ if(_currZoomedItemIndex === _currentItemIndex) {
+ itemChanged = false;
+ }
+
+ _mainScrollAnimating = true;
+
+ _shout('mainScrollAnimStart');
+
+ _animateProp('mainScroll', _mainScrollPos.x, animateToX, finishAnimDuration, framework.easing.cubic.out,
+ _moveMainScroll,
+ function() {
+ _stopAllAnimations();
+ _mainScrollAnimating = false;
+ _currZoomedItemIndex = -1;
+
+ if(itemChanged || _currZoomedItemIndex !== _currentItemIndex) {
+ self.updateCurrItem();
+ }
+
+ _shout('mainScrollAnimComplete');
+ }
+ );
+
+ if(itemChanged) {
+ self.updateCurrItem(true);
+ }
+
+ return itemChanged;
+ },
+
+ _calculateZoomLevel = function(touchesDistance) {
+ return 1 / _startPointsDistance * touchesDistance * _startZoomLevel;
+ },
+
+ // Resets zoom if it's out of bounds
+ _completeZoomGesture = function() {
+ var destZoomLevel = _currZoomLevel,
+ minZoomLevel = _getMinZoomLevel(),
+ maxZoomLevel = _getMaxZoomLevel();
+
+ if ( _currZoomLevel < minZoomLevel ) {
+ destZoomLevel = minZoomLevel;
+ } else if ( _currZoomLevel > maxZoomLevel ) {
+ destZoomLevel = maxZoomLevel;
+ }
+
+ var destOpacity = 1,
+ onUpdate,
+ initialOpacity = _bgOpacity;
+
+ if(_opacityChanged && !_isZoomingIn && !_wasOverInitialZoom && _currZoomLevel < minZoomLevel) {
+ //_closedByScroll = true;
+ self.close();
+ return true;
+ }
+
+ if(_opacityChanged) {
+ onUpdate = function(now) {
+ _applyBgOpacity( (destOpacity - initialOpacity) * now + initialOpacity );
+ };
+ }
+
+ self.zoomTo(destZoomLevel, 0, 200, framework.easing.cubic.out, onUpdate);
+ return true;
+ };
+
+
+_registerModule('Gestures', {
+ publicMethods: {
+
+ initGestures: function() {
+
+ // helper function that builds touch/pointer/mouse events
+ var addEventNames = function(pref, down, move, up, cancel) {
+ _dragStartEvent = pref + down;
+ _dragMoveEvent = pref + move;
+ _dragEndEvent = pref + up;
+ if(cancel) {
+ _dragCancelEvent = pref + cancel;
+ } else {
+ _dragCancelEvent = '';
+ }
+ };
+
+ _pointerEventEnabled = _features.pointerEvent;
+ if(_pointerEventEnabled && _features.touch) {
+ // we don't need touch events, if browser supports pointer events
+ _features.touch = false;
+ }
+
+ if(_pointerEventEnabled) {
+ if(navigator.pointerEnabled) {
+ addEventNames('pointer', 'down', 'move', 'up', 'cancel');
+ } else {
+ // IE10 pointer events are case-sensitive
+ addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel');
+ }
+ } else if(_features.touch) {
+ addEventNames('touch', 'start', 'move', 'end', 'cancel');
+ _likelyTouchDevice = true;
+ } else {
+ addEventNames('mouse', 'down', 'move', 'up');
+ }
+
+ _upMoveEvents = _dragMoveEvent + ' ' + _dragEndEvent + ' ' + _dragCancelEvent;
+ _downEvents = _dragStartEvent;
+
+ if(_pointerEventEnabled && !_likelyTouchDevice) {
+ _likelyTouchDevice = (navigator.maxTouchPoints > 1) || (navigator.msMaxTouchPoints > 1);
+ }
+ // make variable public
+ self.likelyTouchDevice = _likelyTouchDevice;
+
+ _globalEventHandlers[_dragStartEvent] = _onDragStart;
+ _globalEventHandlers[_dragMoveEvent] = _onDragMove;
+ _globalEventHandlers[_dragEndEvent] = _onDragRelease; // the Kraken
+
+ if(_dragCancelEvent) {
+ _globalEventHandlers[_dragCancelEvent] = _globalEventHandlers[_dragEndEvent];
+ }
+
+ // Bind mouse events on device with detected hardware touch support, in case it supports multiple types of input.
+ if(_features.touch) {
+ _downEvents += ' mousedown';
+ _upMoveEvents += ' mousemove mouseup';
+ _globalEventHandlers.mousedown = _globalEventHandlers[_dragStartEvent];
+ _globalEventHandlers.mousemove = _globalEventHandlers[_dragMoveEvent];
+ _globalEventHandlers.mouseup = _globalEventHandlers[_dragEndEvent];
+ }
+
+ if(!_likelyTouchDevice) {
+ // don't allow pan to next slide from zoomed state on Desktop
+ _options.allowPanToNext = false;
+ }
+ }
+
+ }
+});
+
+
+/*>>gestures*/
+
+/*>>show-hide-transition*/
+/**
+ * show-hide-transition.js:
+ *
+ * Manages initial opening or closing transition.
+ *
+ * If you're not planning to use transition for gallery at all,
+ * you may set options hideAnimationDuration and showAnimationDuration to 0,
+ * and just delete startAnimation function.
+ *
+ */
+
+
+var _showOrHideTimeout,
+ _showOrHide = function(item, img, out, completeFn) {
+
+ if(_showOrHideTimeout) {
+ clearTimeout(_showOrHideTimeout);
+ }
+
+ _initialZoomRunning = true;
+ _initialContentSet = true;
+
+ // dimensions of small thumbnail {x:,y:,w:}.
+ // Height is optional, as calculated based on large image.
+ var thumbBounds;
+ if(item.initialLayout) {
+ thumbBounds = item.initialLayout;
+ item.initialLayout = null;
+ } else {
+ thumbBounds = _options.getThumbBoundsFn && _options.getThumbBoundsFn(_currentItemIndex);
+ }
+
+ var duration = out ? _options.hideAnimationDuration : _options.showAnimationDuration;
+
+ var onComplete = function() {
+ _stopAnimation('initialZoom');
+ if(!out) {
+ _applyBgOpacity(1);
+ if(img) {
+ img.style.display = 'block';
+ }
+ framework.addClass(template, 'pswp--animated-in');
+ _shout('initialZoom' + (out ? 'OutEnd' : 'InEnd'));
+ } else {
+ self.template.removeAttribute('style');
+ self.bg.removeAttribute('style');
+ }
+
+ if(completeFn) {
+ completeFn();
+ }
+ _initialZoomRunning = false;
+ };
+
+ // if bounds aren't provided, just open gallery without animation
+ if(!duration || !thumbBounds || thumbBounds.x === undefined) {
+
+ _shout('initialZoom' + (out ? 'Out' : 'In') );
+
+ _currZoomLevel = item.initialZoomLevel;
+ _equalizePoints(_panOffset, item.initialPosition );
+ _applyCurrentZoomPan();
+
+ template.style.opacity = out ? 0 : 1;
+ _applyBgOpacity(1);
+
+ if(duration) {
+ setTimeout(function() {
+ onComplete();
+ }, duration);
+ } else {
+ onComplete();
+ }
+
+ return;
+ }
+
+ var startAnimation = function() {
+ var closeWithRaf = _closedByScroll,
+ fadeEverything = !self.currItem.src || self.currItem.loadError || _options.showHideOpacity;
+
+ // apply hw-acceleration to image
+ if(item.miniImg) {
+ item.miniImg.style.webkitBackfaceVisibility = 'hidden';
+ }
+
+ if(!out) {
+ _currZoomLevel = thumbBounds.w / item.w;
+ _panOffset.x = thumbBounds.x;
+ _panOffset.y = thumbBounds.y - _initalWindowScrollY;
+
+ self[fadeEverything ? 'template' : 'bg'].style.opacity = 0.001;
+ _applyCurrentZoomPan();
+ }
+
+ _registerStartAnimation('initialZoom');
+
+ if(out && !closeWithRaf) {
+ framework.removeClass(template, 'pswp--animated-in');
+ }
+
+ if(fadeEverything) {
+ if(out) {
+ framework[ (closeWithRaf ? 'remove' : 'add') + 'Class' ](template, 'pswp--animate_opacity');
+ } else {
+ setTimeout(function() {
+ framework.addClass(template, 'pswp--animate_opacity');
+ }, 30);
+ }
+ }
+
+ _showOrHideTimeout = setTimeout(function() {
+
+ _shout('initialZoom' + (out ? 'Out' : 'In') );
+
+
+ if(!out) {
+
+ // "in" animation always uses CSS transitions (instead of rAF).
+ // CSS transition work faster here,
+ // as developer may also want to animate other things,
+ // like ui on top of sliding area, which can be animated just via CSS
+
+ _currZoomLevel = item.initialZoomLevel;
+ _equalizePoints(_panOffset, item.initialPosition );
+ _applyCurrentZoomPan();
+ _applyBgOpacity(1);
+
+ if(fadeEverything) {
+ template.style.opacity = 1;
+ } else {
+ _applyBgOpacity(1);
+ }
+
+ _showOrHideTimeout = setTimeout(onComplete, duration + 20);
+ } else {
+
+ // "out" animation uses rAF only when PhotoSwipe is closed by browser scroll, to recalculate position
+ var destZoomLevel = thumbBounds.w / item.w,
+ initialPanOffset = {
+ x: _panOffset.x,
+ y: _panOffset.y
+ },
+ initialZoomLevel = _currZoomLevel,
+ initalBgOpacity = _bgOpacity,
+ onUpdate = function(now) {
+
+ if(now === 1) {
+ _currZoomLevel = destZoomLevel;
+ _panOffset.x = thumbBounds.x;
+ _panOffset.y = thumbBounds.y - _currentWindowScrollY;
+ } else {
+ _currZoomLevel = (destZoomLevel - initialZoomLevel) * now + initialZoomLevel;
+ _panOffset.x = (thumbBounds.x - initialPanOffset.x) * now + initialPanOffset.x;
+ _panOffset.y = (thumbBounds.y - _currentWindowScrollY - initialPanOffset.y) * now + initialPanOffset.y;
+ }
+
+ _applyCurrentZoomPan();
+ if(fadeEverything) {
+ template.style.opacity = 1 - now;
+ } else {
+ _applyBgOpacity( initalBgOpacity - now * initalBgOpacity );
+ }
+ };
+
+ if(closeWithRaf) {
+ _animateProp('initialZoom', 0, 1, duration, framework.easing.cubic.out, onUpdate, onComplete);
+ } else {
+ onUpdate(1);
+ _showOrHideTimeout = setTimeout(onComplete, duration + 20);
+ }
+ }
+
+ }, out ? 25 : 90); // Main purpose of this delay is to give browser time to paint and
+ // create composite layers of PhotoSwipe UI parts (background, controls, caption, arrows).
+ // Which avoids lag at the beginning of scale transition.
+ };
+ startAnimation();
+
+
+ };
+
+/*>>show-hide-transition*/
+
+/*>>items-controller*/
+/**
+*
+* Controller manages gallery items, their dimensions, and their content.
+*
+*/
+
+var _items,
+ _tempPanAreaSize = {},
+ _imagesToAppendPool = [],
+ _initialContentSet,
+ _initialZoomRunning,
+ _controllerDefaultOptions = {
+ index: 0,
+ errorMsg: '',
+ forceProgressiveLoading: false, // TODO
+ preload: [1,1],
+ getNumItemsFn: function() {
+ return _items.length;
+ }
+ };
+
+
+var _getItemAt,
+ _getNumItems,
+ _initialIsLoop,
+ _getZeroBounds = function() {
+ return {
+ center:{x:0,y:0},
+ max:{x:0,y:0},
+ min:{x:0,y:0}
+ };
+ },
+ _calculateSingleItemPanBounds = function(item, realPanElementW, realPanElementH ) {
+ var bounds = item.bounds;
+
+ // position of element when it's centered
+ bounds.center.x = Math.round((_tempPanAreaSize.x - realPanElementW) / 2);
+ bounds.center.y = Math.round((_tempPanAreaSize.y - realPanElementH) / 2) + item.vGap.top;
+
+ // maximum pan position
+ bounds.max.x = (realPanElementW > _tempPanAreaSize.x) ?
+ Math.round(_tempPanAreaSize.x - realPanElementW) :
+ bounds.center.x;
+
+ bounds.max.y = (realPanElementH > _tempPanAreaSize.y) ?
+ Math.round(_tempPanAreaSize.y - realPanElementH) + item.vGap.top :
+ bounds.center.y;
+
+ // minimum pan position
+ bounds.min.x = (realPanElementW > _tempPanAreaSize.x) ? 0 : bounds.center.x;
+ bounds.min.y = (realPanElementH > _tempPanAreaSize.y) ? item.vGap.top : bounds.center.y;
+ },
+ _calculateItemSize = function(item, viewportSize, zoomLevel) {
+
+ if (item.src && !item.loadError) {
+ var isInitial = !zoomLevel;
+
+ if(isInitial) {
+ if(!item.vGap) {
+ item.vGap = {top:0,bottom:0};
+ }
+ // allows overriding vertical margin for individual items
+ _shout('parseVerticalMargin', item);
+ }
+
+
+ _tempPanAreaSize.x = viewportSize.x;
+ _tempPanAreaSize.y = viewportSize.y - item.vGap.top - item.vGap.bottom;
+
+ if (isInitial) {
+ var hRatio = _tempPanAreaSize.x / item.w;
+ var vRatio = _tempPanAreaSize.y / item.h;
+
+ item.fitRatio = hRatio < vRatio ? hRatio : vRatio;
+ //item.fillRatio = hRatio > vRatio ? hRatio : vRatio;
+
+ var scaleMode = _options.scaleMode;
+
+ if (scaleMode === 'orig') {
+ zoomLevel = 1;
+ } else if (scaleMode === 'fit') {
+ zoomLevel = item.fitRatio;
+ }
+
+ if (zoomLevel > 1) {
+ zoomLevel = 1;
+ }
+
+ item.initialZoomLevel = zoomLevel;
+
+ if(!item.bounds) {
+ // reuse bounds object
+ item.bounds = _getZeroBounds();
+ }
+ }
+
+ if(!zoomLevel) {
+ return;
+ }
+
+ _calculateSingleItemPanBounds(item, item.w * zoomLevel, item.h * zoomLevel);
+
+ if (isInitial && zoomLevel === item.initialZoomLevel) {
+ item.initialPosition = item.bounds.center;
+ }
+
+ return item.bounds;
+ } else {
+ item.w = item.h = 0;
+ item.initialZoomLevel = item.fitRatio = 1;
+ item.bounds = _getZeroBounds();
+ item.initialPosition = item.bounds.center;
+
+ // if it's not image, we return zero bounds (content is not zoomable)
+ return item.bounds;
+ }
+
+ },
+
+
+
+
+ _appendImage = function(index, item, baseDiv, img, preventAnimation, keepPlaceholder) {
+
+
+ if(item.loadError) {
+ return;
+ }
+
+ if(img) {
+
+ item.imageAppended = true;
+ _setImageSize(item, img, (item === self.currItem && _renderMaxResolution) );
+
+ baseDiv.appendChild(img);
+
+ if(keepPlaceholder) {
+ setTimeout(function() {
+ if(item && item.loaded && item.placeholder) {
+ item.placeholder.style.display = 'none';
+ item.placeholder = null;
+ }
+ }, 500);
+ }
+ }
+ },
+
+
+
+ _preloadImage = function(item) {
+ item.loading = true;
+ item.loaded = false;
+ var img = item.img = framework.createEl('pswp__img', 'img');
+ var onComplete = function() {
+ item.loading = false;
+ item.loaded = true;
+
+ if(item.loadComplete) {
+ item.loadComplete(item);
+ } else {
+ item.img = null; // no need to store image object
+ }
+ img.onload = img.onerror = null;
+ img = null;
+ };
+ img.onload = onComplete;
+ img.onerror = function() {
+ item.loadError = true;
+ onComplete();
+ };
+
+ img.src = item.src;// + '?a=' + Math.random();
+
+ return img;
+ },
+ _checkForError = function(item, cleanUp) {
+ if(item.src && item.loadError && item.container) {
+
+ if(cleanUp) {
+ item.container.innerHTML = '';
+ }
+
+ item.container.innerHTML = _options.errorMsg.replace('%url%', item.src );
+ return true;
+
+ }
+ },
+ _setImageSize = function(item, img, maxRes) {
+ if(!item.src) {
+ return;
+ }
+
+ if(!img) {
+ img = item.container.lastChild;
+ }
+
+ var w = maxRes ? item.w : Math.round(item.w * item.fitRatio),
+ h = maxRes ? item.h : Math.round(item.h * item.fitRatio);
+
+ if(item.placeholder && !item.loaded) {
+ item.placeholder.style.width = w + 'px';
+ item.placeholder.style.height = h + 'px';
+ }
+
+ img.style.width = w + 'px';
+ img.style.height = h + 'px';
+ },
+ _appendImagesPool = function() {
+
+ if(_imagesToAppendPool.length) {
+ var poolItem;
+
+ for(var i = 0; i < _imagesToAppendPool.length; i++) {
+ poolItem = _imagesToAppendPool[i];
+ if( poolItem.holder.index === poolItem.index ) {
+ _appendImage(poolItem.index, poolItem.item, poolItem.baseDiv, poolItem.img, false, poolItem.clearPlaceholder);
+ }
+ }
+ _imagesToAppendPool = [];
+ }
+ };
+
+
+
+_registerModule('Controller', {
+
+ publicMethods: {
+
+ lazyLoadItem: function(index) {
+ index = _getLoopedId(index);
+ var item = _getItemAt(index);
+
+ if(!item || ((item.loaded || item.loading) && !_itemsNeedUpdate)) {
+ return;
+ }
+
+ _shout('gettingData', index, item);
+
+ if (!item.src) {
+ return;
+ }
+
+ _preloadImage(item);
+ },
+ initController: function() {
+ framework.extend(_options, _controllerDefaultOptions, true);
+ self.items = _items = items;
+ _getItemAt = self.getItemAt;
+ _getNumItems = _options.getNumItemsFn; //self.getNumItems;
+
+
+
+ _initialIsLoop = _options.loop;
+ if(_getNumItems() < 3) {
+ _options.loop = false; // disable loop if less then 3 items
+ }
+
+ _listen('beforeChange', function(diff) {
+
+ var p = _options.preload,
+ isNext = diff === null ? true : (diff >= 0),
+ preloadBefore = Math.min(p[0], _getNumItems() ),
+ preloadAfter = Math.min(p[1], _getNumItems() ),
+ i;
+
+
+ for(i = 1; i <= (isNext ? preloadAfter : preloadBefore); i++) {
+ self.lazyLoadItem(_currentItemIndex+i);
+ }
+ for(i = 1; i <= (isNext ? preloadBefore : preloadAfter); i++) {
+ self.lazyLoadItem(_currentItemIndex-i);
+ }
+ });
+
+ _listen('initialLayout', function() {
+ self.currItem.initialLayout = _options.getThumbBoundsFn && _options.getThumbBoundsFn(_currentItemIndex);
+ });
+
+ _listen('mainScrollAnimComplete', _appendImagesPool);
+ _listen('initialZoomInEnd', _appendImagesPool);
+
+
+
+ _listen('destroy', function() {
+ var item;
+ for(var i = 0; i < _items.length; i++) {
+ item = _items[i];
+ // remove reference to DOM elements, for GC
+ if(item.container) {
+ item.container = null;
+ }
+ if(item.placeholder) {
+ item.placeholder = null;
+ }
+ if(item.img) {
+ item.img = null;
+ }
+ if(item.preloader) {
+ item.preloader = null;
+ }
+ if(item.loadError) {
+ item.loaded = item.loadError = false;
+ }
+ }
+ _imagesToAppendPool = null;
+ });
+ },
+
+
+ getItemAt: function(index) {
+ if (index >= 0) {
+ return _items[index] !== undefined ? _items[index] : false;
+ }
+ return false;
+ },
+
+ allowProgressiveImg: function() {
+ // 1. Progressive image loading isn't working on webkit/blink
+ // when hw-acceleration (e.g. translateZ) is applied to IMG element.
+ // That's why in PhotoSwipe parent element gets zoom transform, not image itself.
+ //
+ // 2. Progressive image loading sometimes blinks in webkit/blink when applying animation to parent element.
+ // That's why it's disabled on touch devices (mainly because of swipe transition)
+ //
+ // 3. Progressive image loading sometimes doesn't work in IE (up to 11).
+
+ // Don't allow progressive loading on non-large touch devices
+ return _options.forceProgressiveLoading || !_likelyTouchDevice || _options.mouseUsed || screen.width > 1200;
+ // 1200 - to eliminate touch devices with large screen (like Chromebook Pixel)
+ },
+
+ setContent: function(holder, index) {
+
+ if(_options.loop) {
+ index = _getLoopedId(index);
+ }
+
+ var prevItem = self.getItemAt(holder.index);
+ if(prevItem) {
+ prevItem.container = null;
+ }
+
+ var item = self.getItemAt(index),
+ img;
+
+ if(!item) {
+ holder.el.innerHTML = '';
+ return;
+ }
+
+ // allow to override data
+ _shout('gettingData', index, item);
+
+ holder.index = index;
+ holder.item = item;
+
+ // base container DIV is created only once for each of 3 holders
+ var baseDiv = item.container = framework.createEl('pswp__zoom-wrap');
+
+
+
+ if(!item.src && item.html) {
+ if(item.html.tagName) {
+ baseDiv.appendChild(item.html);
+ } else {
+ baseDiv.innerHTML = item.html;
+ }
+ }
+
+ _checkForError(item);
+
+ _calculateItemSize(item, _viewportSize);
+
+ if(item.src && !item.loadError && !item.loaded) {
+
+ item.loadComplete = function(item) {
+
+ // gallery closed before image finished loading
+ if(!_isOpen) {
+ return;
+ }
+
+ // check if holder hasn't changed while image was loading
+ if(holder && holder.index === index ) {
+ if( _checkForError(item, true) ) {
+ item.loadComplete = item.img = null;
+ _calculateItemSize(item, _viewportSize);
+ _applyZoomPanToItem(item);
+
+ if(holder.index === _currentItemIndex) {
+ // recalculate dimensions
+ self.updateCurrZoomItem();
+ }
+ return;
+ }
+ if( !item.imageAppended ) {
+ if(_features.transform && (_mainScrollAnimating || _initialZoomRunning) ) {
+ _imagesToAppendPool.push({
+ item:item,
+ baseDiv:baseDiv,
+ img:item.img,
+ index:index,
+ holder:holder,
+ clearPlaceholder:true
+ });
+ } else {
+ _appendImage(index, item, baseDiv, item.img, _mainScrollAnimating || _initialZoomRunning, true);
+ }
+ } else {
+ // remove preloader & mini-img
+ if(!_initialZoomRunning && item.placeholder) {
+ item.placeholder.style.display = 'none';
+ item.placeholder = null;
+ }
+ }
+ }
+
+ item.loadComplete = null;
+ item.img = null; // no need to store image element after it's added
+
+ _shout('imageLoadComplete', index, item);
+ };
+
+ if(framework.features.transform) {
+
+ var placeholderClassName = 'pswp__img pswp__img--placeholder';
+ placeholderClassName += (item.msrc ? '' : ' pswp__img--placeholder--blank');
+
+ var placeholder = framework.createEl(placeholderClassName, item.msrc ? 'img' : '');
+ if(item.msrc) {
+ placeholder.src = item.msrc;
+ }
+
+ _setImageSize(item, placeholder);
+
+ baseDiv.appendChild(placeholder);
+ item.placeholder = placeholder;
+
+ }
+
+
+
+
+ if(!item.loading) {
+ _preloadImage(item);
+ }
+
+
+ if( self.allowProgressiveImg() ) {
+ // just append image
+ if(!_initialContentSet && _features.transform) {
+ _imagesToAppendPool.push({
+ item:item,
+ baseDiv:baseDiv,
+ img:item.img,
+ index:index,
+ holder:holder
+ });
+ } else {
+ _appendImage(index, item, baseDiv, item.img, true, true);
+ }
+ }
+
+ } else if(item.src && !item.loadError) {
+ // image object is created every time, due to bugs of image loading & delay when switching images
+ img = framework.createEl('pswp__img', 'img');
+ img.style.opacity = 1;
+ img.src = item.src;
+ _setImageSize(item, img);
+ _appendImage(index, item, baseDiv, img, true);
+ }
+
+
+ if(!_initialContentSet && index === _currentItemIndex) {
+ _currZoomElementStyle = baseDiv.style;
+ _showOrHide(item, (img ||item.img) );
+ } else {
+ _applyZoomPanToItem(item);
+ }
+
+ holder.el.innerHTML = '';
+ holder.el.appendChild(baseDiv);
+ },
+
+ cleanSlide: function( item ) {
+ if(item.img ) {
+ item.img.onload = item.img.onerror = null;
+ }
+ item.loaded = item.loading = item.img = item.imageAppended = false;
+ }
+
+ }
+});
+
+/*>>items-controller*/
+
+/*>>tap*/
+/**
+ * tap.js:
+ *
+ * Displatches tap and double-tap events.
+ *
+ */
+
+var tapTimer,
+ tapReleasePoint = {},
+ _dispatchTapEvent = function(origEvent, releasePoint, pointerType) {
+ var e = document.createEvent( 'CustomEvent' ),
+ eDetail = {
+ origEvent:origEvent,
+ target:origEvent.target,
+ releasePoint: releasePoint,
+ pointerType:pointerType || 'touch'
+ };
+
+ e.initCustomEvent( 'pswpTap', true, true, eDetail );
+ origEvent.target.dispatchEvent(e);
+ };
+
+_registerModule('Tap', {
+ publicMethods: {
+ initTap: function() {
+ _listen('firstTouchStart', self.onTapStart);
+ _listen('touchRelease', self.onTapRelease);
+ _listen('destroy', function() {
+ tapReleasePoint = {};
+ tapTimer = null;
+ });
+ },
+ onTapStart: function(touchList) {
+ if(touchList.length > 1) {
+ clearTimeout(tapTimer);
+ tapTimer = null;
+ }
+ },
+ onTapRelease: function(e, releasePoint) {
+ if(!releasePoint) {
+ return;
+ }
+
+ if(!_moved && !_isMultitouch && !_numAnimations) {
+ var p0 = releasePoint;
+ if(tapTimer) {
+ clearTimeout(tapTimer);
+ tapTimer = null;
+
+ // Check if taped on the same place
+ if ( _isNearbyPoints(p0, tapReleasePoint) ) {
+ _shout('doubleTap', p0);
+ return;
+ }
+ }
+
+ if(releasePoint.type === 'mouse') {
+ _dispatchTapEvent(e, releasePoint, 'mouse');
+ return;
+ }
+
+ var clickedTagName = e.target.tagName.toUpperCase();
+ // avoid double tap delay on buttons and elements that have class pswp__single-tap
+ if(clickedTagName === 'BUTTON' || framework.hasClass(e.target, 'pswp__single-tap') ) {
+ _dispatchTapEvent(e, releasePoint);
+ return;
+ }
+
+ _equalizePoints(tapReleasePoint, p0);
+
+ tapTimer = setTimeout(function() {
+ _dispatchTapEvent(e, releasePoint);
+ tapTimer = null;
+ }, 300);
+ }
+ }
+ }
+});
+
+/*>>tap*/
+
+/*>>desktop-zoom*/
+/**
+ *
+ * desktop-zoom.js:
+ *
+ * - Binds mousewheel event for paning zoomed image.
+ * - Manages "dragging", "zoomed-in", "zoom-out" classes.
+ * (which are used for cursors and zoom icon)
+ * - Adds toggleDesktopZoom function.
+ *
+ */
+
+var _wheelDelta;
+
+_registerModule('DesktopZoom', {
+
+ publicMethods: {
+
+ initDesktopZoom: function() {
+
+ if(_oldIE) {
+ // no zoom for old IE (<=8)
+ return;
+ }
+
+ if(_likelyTouchDevice) {
+ // if detected hardware touch support, we wait until mouse is used,
+ // and only then apply desktop-zoom features
+ _listen('mouseUsed', function() {
+ self.setupDesktopZoom();
+ });
+ } else {
+ self.setupDesktopZoom(true);
+ }
+
+ },
+
+ setupDesktopZoom: function(onInit) {
+
+ _wheelDelta = {};
+
+ var events = 'wheel mousewheel DOMMouseScroll';
+
+ _listen('bindEvents', function() {
+ framework.bind(template, events, self.handleMouseWheel);
+ });
+
+ _listen('unbindEvents', function() {
+ if(_wheelDelta) {
+ framework.unbind(template, events, self.handleMouseWheel);
+ }
+ });
+
+ self.mouseZoomedIn = false;
+
+ var hasDraggingClass,
+ updateZoomable = function() {
+ if(self.mouseZoomedIn) {
+ framework.removeClass(template, 'pswp--zoomed-in');
+ self.mouseZoomedIn = false;
+ }
+ if(_currZoomLevel < 1) {
+ framework.addClass(template, 'pswp--zoom-allowed');
+ } else {
+ framework.removeClass(template, 'pswp--zoom-allowed');
+ }
+ removeDraggingClass();
+ },
+ removeDraggingClass = function() {
+ if(hasDraggingClass) {
+ framework.removeClass(template, 'pswp--dragging');
+ hasDraggingClass = false;
+ }
+ };
+
+ _listen('resize' , updateZoomable);
+ _listen('afterChange' , updateZoomable);
+ _listen('pointerDown', function() {
+ if(self.mouseZoomedIn) {
+ hasDraggingClass = true;
+ framework.addClass(template, 'pswp--dragging');
+ }
+ });
+ _listen('pointerUp', removeDraggingClass);
+
+ if(!onInit) {
+ updateZoomable();
+ }
+
+ },
+
+ handleMouseWheel: function(e) {
+
+ if(_currZoomLevel <= self.currItem.fitRatio) {
+ if( _options.modal ) {
+
+ if (!_options.closeOnScroll || _numAnimations || _isDragging) {
+ e.preventDefault();
+ } else if(_transformKey && Math.abs(e.deltaY) > 2) {
+ // close PhotoSwipe
+ // if browser supports transforms & scroll changed enough
+ _closedByScroll = true;
+ self.close();
+ }
+
+ }
+ return true;
+ }
+
+ // allow just one event to fire
+ e.stopPropagation();
+
+ // https://developer.mozilla.org/en-US/docs/Web/Events/wheel
+ _wheelDelta.x = 0;
+
+ if('deltaX' in e) {
+ if(e.deltaMode === 1 /* DOM_DELTA_LINE */) {
+ // 18 - average line height
+ _wheelDelta.x = e.deltaX * 18;
+ _wheelDelta.y = e.deltaY * 18;
+ } else {
+ _wheelDelta.x = e.deltaX;
+ _wheelDelta.y = e.deltaY;
+ }
+ } else if('wheelDelta' in e) {
+ if(e.wheelDeltaX) {
+ _wheelDelta.x = -0.16 * e.wheelDeltaX;
+ }
+ if(e.wheelDeltaY) {
+ _wheelDelta.y = -0.16 * e.wheelDeltaY;
+ } else {
+ _wheelDelta.y = -0.16 * e.wheelDelta;
+ }
+ } else if('detail' in e) {
+ _wheelDelta.y = e.detail;
+ } else {
+ return;
+ }
+
+ _calculatePanBounds(_currZoomLevel, true);
+
+ var newPanX = _panOffset.x - _wheelDelta.x,
+ newPanY = _panOffset.y - _wheelDelta.y;
+
+ // only prevent scrolling in nonmodal mode when not at edges
+ if (_options.modal ||
+ (
+ newPanX <= _currPanBounds.min.x && newPanX >= _currPanBounds.max.x &&
+ newPanY <= _currPanBounds.min.y && newPanY >= _currPanBounds.max.y
+ ) ) {
+ e.preventDefault();
+ }
+
+ // TODO: use rAF instead of mousewheel?
+ self.panTo(newPanX, newPanY);
+ },
+
+ toggleDesktopZoom: function(centerPoint) {
+ centerPoint = centerPoint || {x:_viewportSize.x/2 + _offset.x, y:_viewportSize.y/2 + _offset.y };
+
+ var doubleTapZoomLevel = _options.getDoubleTapZoom(true, self.currItem);
+ var zoomOut = _currZoomLevel === doubleTapZoomLevel;
+
+ self.mouseZoomedIn = !zoomOut;
+
+ self.zoomTo(zoomOut ? self.currItem.initialZoomLevel : doubleTapZoomLevel, centerPoint, 333);
+ framework[ (!zoomOut ? 'add' : 'remove') + 'Class'](template, 'pswp--zoomed-in');
+ }
+
+ }
+});
+
+
+/*>>desktop-zoom*/
+
+/*>>history*/
+/**
+ *
+ * history.js:
+ *
+ * - Back button to close gallery.
+ *
+ * - Unique URL for each slide: example.com/&pid=1&gid=3
+ * (where PID is picture index, and GID and gallery index)
+ *
+ * - Switch URL when slides change.
+ *
+ */
+
+
+var _historyDefaultOptions = {
+ history: true,
+ galleryUID: 1
+};
+
+var _historyUpdateTimeout,
+ _hashChangeTimeout,
+ _hashAnimCheckTimeout,
+ _hashChangedByScript,
+ _hashChangedByHistory,
+ _hashReseted,
+ _initialHash,
+ _historyChanged,
+ _closedFromURL,
+ _urlChangedOnce,
+ _windowLoc,
+
+ _supportsPushState,
+
+ _getHash = function() {
+ return _windowLoc.hash.substring(1);
+ },
+ _cleanHistoryTimeouts = function() {
+
+ if(_historyUpdateTimeout) {
+ clearTimeout(_historyUpdateTimeout);
+ }
+
+ if(_hashAnimCheckTimeout) {
+ clearTimeout(_hashAnimCheckTimeout);
+ }
+ },
+
+ // pid - Picture index
+ // gid - Gallery index
+ _parseItemIndexFromURL = function() {
+ var hash = _getHash(),
+ params = {};
+
+ if(hash.length < 5) { // pid=1
+ return params;
+ }
+
+ var i, vars = hash.split('&');
+ for (i = 0; i < vars.length; i++) {
+ if(!vars[i]) {
+ continue;
+ }
+ var pair = vars[i].split('=');
+ if(pair.length < 2) {
+ continue;
+ }
+ params[pair[0]] = pair[1];
+ }
+ if(_options.galleryPIDs) {
+ // detect custom pid in hash and search for it among the items collection
+ var searchfor = params.pid;
+ params.pid = 0; // if custom pid cannot be found, fallback to the first item
+ for(i = 0; i < _items.length; i++) {
+ if(_items[i].pid === searchfor) {
+ params.pid = i;
+ break;
+ }
+ }
+ } else {
+ params.pid = parseInt(params.pid,10)-1;
+ }
+ if( params.pid < 0 ) {
+ params.pid = 0;
+ }
+ return params;
+ },
+ _updateHash = function() {
+
+ if(_hashAnimCheckTimeout) {
+ clearTimeout(_hashAnimCheckTimeout);
+ }
+
+
+ if(_numAnimations || _isDragging) {
+ // changing browser URL forces layout/paint in some browsers, which causes noticable lag during animation
+ // that's why we update hash only when no animations running
+ _hashAnimCheckTimeout = setTimeout(_updateHash, 500);
+ return;
+ }
+
+ if(_hashChangedByScript) {
+ clearTimeout(_hashChangeTimeout);
+ } else {
+ _hashChangedByScript = true;
+ }
+
+
+ var pid = (_currentItemIndex + 1);
+ var item = _getItemAt( _currentItemIndex );
+ if(item.hasOwnProperty('pid')) {
+ // carry forward any custom pid assigned to the item
+ pid = item.pid;
+ }
+ var newHash = _initialHash + '&' + 'gid=' + _options.galleryUID + '&' + 'pid=' + pid;
+
+ if(!_historyChanged) {
+ if(_windowLoc.hash.indexOf(newHash) === -1) {
+ _urlChangedOnce = true;
+ }
+ // first time - add new hisory record, then just replace
+ }
+
+ var newURL = _windowLoc.href.split('#')[0] + '#' + newHash;
+
+ if( _supportsPushState ) {
+
+ if('#' + newHash !== window.location.hash) {
+ history[_historyChanged ? 'replaceState' : 'pushState']('', document.title, newURL);
+ }
+
+ } else {
+ if(_historyChanged) {
+ _windowLoc.replace( newURL );
+ } else {
+ _windowLoc.hash = newHash;
+ }
+ }
+
+
+
+ _historyChanged = true;
+ _hashChangeTimeout = setTimeout(function() {
+ _hashChangedByScript = false;
+ }, 60);
+ };
+
+
+
+
+
+_registerModule('History', {
+
+
+
+ publicMethods: {
+ initHistory: function() {
+
+ framework.extend(_options, _historyDefaultOptions, true);
+
+ if( !_options.history ) {
+ return;
+ }
+
+
+ _windowLoc = window.location;
+ _urlChangedOnce = false;
+ _closedFromURL = false;
+ _historyChanged = false;
+ _initialHash = _getHash();
+ _supportsPushState = ('pushState' in history);
+
+
+ if(_initialHash.indexOf('gid=') > -1) {
+ _initialHash = _initialHash.split('&gid=')[0];
+ _initialHash = _initialHash.split('?gid=')[0];
+ }
+
+
+ _listen('afterChange', self.updateURL);
+ _listen('unbindEvents', function() {
+ framework.unbind(window, 'hashchange', self.onHashChange);
+ });
+
+
+ var returnToOriginal = function() {
+ _hashReseted = true;
+ if(!_closedFromURL) {
+
+ if(_urlChangedOnce) {
+ history.back();
+ } else {
+
+ if(_initialHash) {
+ _windowLoc.hash = _initialHash;
+ } else {
+ if (_supportsPushState) {
+
+ // remove hash from url without refreshing it or scrolling to top
+ history.pushState('', document.title, _windowLoc.pathname + _windowLoc.search );
+ } else {
+ _windowLoc.hash = '';
+ }
+ }
+ }
+
+ }
+
+ _cleanHistoryTimeouts();
+ };
+
+
+ _listen('unbindEvents', function() {
+ if(_closedByScroll) {
+ // if PhotoSwipe is closed by scroll, we go "back" before the closing animation starts
+ // this is done to keep the scroll position
+ returnToOriginal();
+ }
+ });
+ _listen('destroy', function() {
+ if(!_hashReseted) {
+ returnToOriginal();
+ }
+ });
+ _listen('firstUpdate', function() {
+ _currentItemIndex = _parseItemIndexFromURL().pid;
+ });
+
+
+
+
+ var index = _initialHash.indexOf('pid=');
+ if(index > -1) {
+ _initialHash = _initialHash.substring(0, index);
+ if(_initialHash.slice(-1) === '&') {
+ _initialHash = _initialHash.slice(0, -1);
+ }
+ }
+
+
+ setTimeout(function() {
+ if(_isOpen) { // hasn't destroyed yet
+ framework.bind(window, 'hashchange', self.onHashChange);
+ }
+ }, 40);
+
+ },
+ onHashChange: function() {
+
+ if(_getHash() === _initialHash) {
+
+ _closedFromURL = true;
+ self.close();
+ return;
+ }
+ if(!_hashChangedByScript) {
+
+ _hashChangedByHistory = true;
+ self.goTo( _parseItemIndexFromURL().pid );
+ _hashChangedByHistory = false;
+ }
+
+ },
+ updateURL: function() {
+
+ // Delay the update of URL, to avoid lag during transition,
+ // and to not to trigger actions like "refresh page sound" or "blinking favicon" to often
+
+ _cleanHistoryTimeouts();
+
+
+ if(_hashChangedByHistory) {
+ return;
+ }
+
+ if(!_historyChanged) {
+ _updateHash(); // first time
+ } else {
+ _historyUpdateTimeout = setTimeout(_updateHash, 800);
+ }
+ }
+
+ }
+});
+
+
+/*>>history*/
+ framework.extend(self, publicMethods); };
+ return PhotoSwipe;
+});
\ No newline at end of file
diff --git a/sigal/themes/photoswipe/static/photoswipe.min.js b/sigal/themes/photoswipe/static/photoswipe.min.js
index 913e783..1fff307 100644
--- a/sigal/themes/photoswipe/static/photoswipe.min.js
+++ b/sigal/themes/photoswipe/static/photoswipe.min.js
@@ -1,4 +1,4 @@
-/*! PhotoSwipe - v4.1.1 - 2015-12-24
+/*! PhotoSwipe - v4.1.2 - 2017-04-05
* http://photoswipe.com
-* Copyright (c) 2015 Dmitry Semenov; */
-!function(a,b){"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():a.PhotoSwipe=b()}(this,function(){"use strict";var a=function(a,b,c,d){var e={features:null,bind:function(a,b,c,d){var e=(d?"remove":"add")+"EventListener";b=b.split(" ");for(var f=0;f0&&(g=parseInt(g[1],10),g>=1&&8>g&&(d.isOldIOSPhone=!0))}var h=f.match(/Android\s([0-9\.]*)/),i=h?h[1]:0;i=parseFloat(i),i>=1&&(4.4>i&&(d.isOldAndroid=!0),d.androidVersion=i),d.isMobileOpera=/opera mini|opera mobi/i.test(f)}for(var j,k,l=["transform","perspective","animationName"],m=["","webkit","Moz","ms","O"],n=0;4>n;n++){c=m[n];for(var o=0;3>o;o++)j=l[o],k=c+(c?j.charAt(0).toUpperCase()+j.slice(1):j),!d[j]&&k in b&&(d[j]=k);c&&!d.raf&&(c=c.toLowerCase(),d.raf=window[c+"RequestAnimationFrame"],d.raf&&(d.caf=window[c+"CancelAnimationFrame"]||window[c+"CancelRequestAnimationFrame"]))}if(!d.raf){var p=0;d.raf=function(a){var b=(new Date).getTime(),c=Math.max(0,16-(b-p)),d=window.setTimeout(function(){a(b+c)},c);return p=b+c,d},d.caf=function(a){clearTimeout(a)}}return d.svg=!!document.createElementNS&&!!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,e.features=d,d}};e.detectFeatures(),e.features.oldIE&&(e.bind=function(a,b,c,d){b=b.split(" ");for(var e,f=(d?"detach":"attach")+"Event",g=function(){c.handleEvent.call(c)},h=0;hb-1?a-b:0>a?b+a:a},Aa={},Ba=function(a,b){return Aa[a]||(Aa[a]=[]),Aa[a].push(b)},Ca=function(a){var b=Aa[a];if(b){var c=Array.prototype.slice.call(arguments);c.shift();for(var d=0;df.currItem.fitRatio?xa||(lc(f.currItem,!1,!0),xa=!0):xa&&(lc(f.currItem),xa=!1)),Fa(da,oa.x,oa.y,s))},Ha=function(a){a.container&&Fa(a.container.style,a.initialPosition.x,a.initialPosition.y,a.initialZoomLevel,a)},Ia=function(a,b){b[E]=u+a+"px, 0px"+v},Ja=function(a,b){if(!i.loop&&b){var c=m+(sa.x*qa-a)/sa.x,d=Math.round(a-sb.x);(0>c&&d>0||c>=_b()-1&&0>d)&&(a=sb.x+d*i.mainScrollEndFriction)}sb.x=a,Ia(a,n)},Ka=function(a,b){var c=tb[a]-ra[a];return na[a]+ma[a]+c-c*(b/t)},La=function(a,b){a.x=b.x,a.y=b.y,b.id&&(a.id=b.id)},Ma=function(a){a.x=Math.round(a.x),a.y=Math.round(a.y)},Na=null,Oa=function(){Na&&(e.unbind(document,"mousemove",Oa),e.addClass(a,"pswp--has_mouse"),i.mouseUsed=!0,Ca("mouseUsed")),Na=setTimeout(function(){Na=null},100)},Pa=function(){e.bind(document,"keydown",f),N.transform&&e.bind(f.scrollWrap,"click",f),i.mouseUsed||e.bind(document,"mousemove",Oa),e.bind(window,"resize scroll",f),Ca("bindEvents")},Qa=function(){e.unbind(window,"resize",f),e.unbind(window,"scroll",r.scroll),e.unbind(document,"keydown",f),e.unbind(document,"mousemove",Oa),N.transform&&e.unbind(f.scrollWrap,"click",f),U&&e.unbind(window,p,f),Ca("unbindEvents")},Ra=function(a,b){var c=hc(f.currItem,pa,a);return b&&(ca=c),c},Sa=function(a){return a||(a=f.currItem),a.initialZoomLevel},Ta=function(a){return a||(a=f.currItem),a.w>0?i.maxSpreadZoom:1},Ua=function(a,b,c,d){return d===f.currItem.initialZoomLevel?(c[a]=f.currItem.initialPosition[a],!0):(c[a]=Ka(a,d),c[a]>b.min[a]?(c[a]=b.min[a],!0):c[a]1?1:a.fitRatio,c=a.container.style,d=b*a.w,e=b*a.h;c.width=d+"px",c.height=e+"px",c.left=a.initialPosition.x+"px",c.top=a.initialPosition.y+"px"},Ga=function(){if(da){var a=da,b=f.currItem,c=b.fitRatio>1?1:b.fitRatio,d=c*b.w,e=c*b.h;a.width=d+"px",a.height=e+"px",a.left=oa.x+"px",a.top=oa.y+"px"}}},Wa=function(a){var b="";i.escKey&&27===a.keyCode?b="close":i.arrowKeys&&(37===a.keyCode?b="prev":39===a.keyCode&&(b="next")),b&&(a.ctrlKey||a.altKey||a.shiftKey||a.metaKey||(a.preventDefault?a.preventDefault():a.returnValue=!1,f[b]()))},Xa=function(a){a&&(X||W||ea||S)&&(a.preventDefault(),a.stopPropagation())},Ya=function(){f.setScrollOffset(0,e.getScrollY())},Za={},$a=0,_a=function(a){Za[a]&&(Za[a].raf&&I(Za[a].raf),$a--,delete Za[a])},ab=function(a){Za[a]&&_a(a),Za[a]||($a++,Za[a]={})},bb=function(){for(var a in Za)Za.hasOwnProperty(a)&&_a(a)},cb=function(a,b,c,d,e,f,g){var h,i=Da();ab(a);var j=function(){if(Za[a]){if(h=Da()-i,h>=d)return _a(a),f(c),void(g&&g());f((c-b)*e(h/d)+b),Za[a].raf=H(j)}};j()},db={shout:Ca,listen:Ba,viewportSize:pa,options:i,isMainScrollAnimating:function(){return ea},getZoomLevel:function(){return s},getCurrentIndex:function(){return m},isDragging:function(){return U},isZooming:function(){return _},setScrollOffset:function(a,b){ra.x=a,M=ra.y=b,Ca("updateScrollOffset",ra)},applyZoomPan:function(a,b,c,d){oa.x=b,oa.y=c,s=a,Ga(d)},init:function(){if(!j&&!k){var c;f.framework=e,f.template=a,f.bg=e.getChildByClass(a,"pswp__bg"),J=a.className,j=!0,N=e.detectFeatures(),H=N.raf,I=N.caf,E=N.transform,L=N.oldIE,f.scrollWrap=e.getChildByClass(a,"pswp__scroll-wrap"),f.container=e.getChildByClass(f.scrollWrap,"pswp__container"),n=f.container.style,f.itemHolders=y=[{el:f.container.children[0],wrap:0,index:-1},{el:f.container.children[1],wrap:0,index:-1},{el:f.container.children[2],wrap:0,index:-1}],y[0].el.style.display=y[2].el.style.display="none",Va(),r={resize:f.updateSize,scroll:Ya,keydown:Wa,click:Xa};var d=N.isOldIOSPhone||N.isOldAndroid||N.isMobileOpera;for(N.animationName&&N.transform&&!d||(i.showAnimationDuration=i.hideAnimationDuration=0),c=0;cm||m>=_b())&&(m=0),f.currItem=$b(m),(N.isOldIOSPhone||N.isOldAndroid)&&(ua=!1),a.setAttribute("aria-hidden","false"),i.modal&&(ua?a.style.position="fixed":(a.style.position="absolute",a.style.top=e.getScrollY()+"px")),void 0===M&&(Ca("initialLayout"),M=K=e.getScrollY());var l="pswp--open ";for(i.mainClass&&(l+=i.mainClass+" "),i.showHideOpacity&&(l+="pswp--animate_opacity "),l+=G?"pswp--touch":"pswp--notouch",l+=N.animationName?" pswp--css_animation":"",l+=N.svg?" pswp--svg":"",e.addClass(a,l),f.updateSize(),o=-1,ta=null,c=0;h>c;c++)Ia((c+o)*sa.x,y[c].el.style);L||e.bind(f.scrollWrap,q,f),Ba("initialZoomInEnd",function(){f.setContent(y[0],m-1),f.setContent(y[2],m+1),y[0].el.style.display=y[2].el.style.display="block",i.focus&&a.focus(),Pa()}),f.setContent(y[1],m),f.updateCurrItem(),Ca("afterInit"),ua||(w=setInterval(function(){$a||U||_||s!==f.currItem.initialZoomLevel||f.updateSize()},1e3)),e.addClass(a,"pswp--visible")}},close:function(){j&&(j=!1,k=!0,Ca("close"),Qa(),bc(f.currItem,null,!0,f.destroy))},destroy:function(){Ca("destroy"),Wb&&clearTimeout(Wb),a.setAttribute("aria-hidden","true"),a.className=J,w&&clearInterval(w),e.unbind(f.scrollWrap,q,f),e.unbind(window,"scroll",f),yb(),bb(),Aa=null},panTo:function(a,b,c){c||(a>ca.min.x?a=ca.min.x:aca.min.y?b=ca.min.y:ba;a++)y[a].item&&(y[a].item.needsUpdate=!0)},updateCurrItem:function(a){if(0!==ta){var b,c=Math.abs(ta);if(!(a&&2>c)){f.currItem=$b(m),xa=!1,Ca("beforeChange",ta),c>=h&&(o+=ta+(ta>0?-h:h),c=h);for(var d=0;c>d;d++)ta>0?(b=y.shift(),y[h-1]=b,o++,Ia((o+2)*sa.x,b.el.style),f.setContent(b,m-c+d+1+1)):(b=y.pop(),y.unshift(b),o--,Ia(o*sa.x,b.el.style),f.setContent(b,m+c-d-1-1));if(da&&1===Math.abs(ta)){var e=$b(z);e.initialZoomLevel!==s&&(hc(e,pa),lc(e),Ha(e))}ta=0,f.updateCurrZoomItem(),z=m,Ca("afterChange")}}},updateSize:function(b){if(!ua&&i.modal){var c=e.getScrollY();if(M!==c&&(a.style.top=c+"px",M=c),!b&&wa.x===window.innerWidth&&wa.y===window.innerHeight)return;wa.x=window.innerWidth,wa.y=window.innerHeight,a.style.height=wa.y+"px"}if(pa.x=f.scrollWrap.clientWidth,pa.y=f.scrollWrap.clientHeight,Ya(),sa.x=pa.x+Math.round(pa.x*i.spacing),sa.y=pa.y,Ja(sa.x*qa),Ca("beforeResize"),void 0!==o){for(var d,g,j,k=0;h>k;k++)d=y[k],Ia((k+o)*sa.x,d.el.style),j=m+k-1,i.loop&&_b()>2&&(j=za(j)),g=$b(j),g&&(x||g.needsUpdate||!g.bounds)?(f.cleanSlide(g),f.setContent(d,j),1===k&&(f.currItem=g,f.updateCurrZoomItem(!0)),g.needsUpdate=!1):-1===d.index&&j>=0&&f.setContent(d,j),g&&g.container&&(hc(g,pa),lc(g),Ha(g));x=!1}t=s=f.currItem.initialZoomLevel,ca=f.currItem.bounds,ca&&(oa.x=ca.center.x,oa.y=ca.center.y,Ga(!0)),Ca("resize")},zoomTo:function(a,b,c,d,f){b&&(t=s,tb.x=Math.abs(b.x)-oa.x,tb.y=Math.abs(b.y)-oa.y,La(na,oa));var g=Ra(a,!1),h={};Ua("x",g,h,a),Ua("y",g,h,a);var i=s,j={x:oa.x,y:oa.y};Ma(h);var k=function(b){1===b?(s=a,oa.x=h.x,oa.y=h.y):(s=(a-i)*b+i,oa.x=(h.x-j.x)*b+j.x,oa.y=(h.y-j.y)*b+j.y),f&&f(b),Ga(1===b)};c?cb("customZoomTo",0,1,c,d||e.easing.sine.inOut,k):k(1)}},eb=30,fb=10,gb={},hb={},ib={},jb={},kb={},lb=[],mb={},nb=[],ob={},pb=0,qb=la(),rb=0,sb=la(),tb=la(),ub=la(),vb=function(a,b){return a.x===b.x&&a.y===b.y},wb=function(a,b){return Math.abs(a.x-b.x)-1?!1:b(a)?a:Bb(a.parentNode,b):!1},Cb={},Db=function(a,b){return Cb.prevent=!Bb(a.target,i.isClickableElement),Ca("preventDragEvent",a,b,Cb),Cb.prevent},Eb=function(a,b){return b.x=a.pageX,b.y=a.pageY,b.id=a.identifier,b},Fb=function(a,b,c){c.x=.5*(a.x+b.x),c.y=.5*(a.y+b.y)},Gb=function(a,b,c){if(a-P>50){var d=nb.length>2?nb.shift():{};d.x=b,d.y=c,nb.push(d),P=a}},Hb=function(){var a=oa.y-f.currItem.initialPosition.y;return 1-Math.abs(a/(pa.y/2))},Ib={},Jb={},Kb=[],Lb=function(a){for(;Kb.length>0;)Kb.pop();return F?(ka=0,lb.forEach(function(a){0===ka?Kb[0]=a:1===ka&&(Kb[1]=a),ka++})):a.type.indexOf("touch")>-1?a.touches&&a.touches.length>0&&(Kb[0]=Eb(a.touches[0],Ib),a.touches.length>1&&(Kb[1]=Eb(a.touches[1],Jb))):(Ib.x=a.pageX,Ib.y=a.pageY,Ib.id="",Kb[0]=Ib),Kb},Mb=function(a,b){var c,d,e,g,h=0,j=oa[a]+b[a],k=b[a]>0,l=sb.x+b.x,m=sb.x-mb.x;return c=j>ca.min[a]||jca.min[a]&&(c=i.panEndFriction,h=ca.min[a]-j,d=ca.min[a]-na[a]),(0>=d||0>m)&&_b()>1?(g=l,0>m&&l>mb.x&&(g=mb.x)):ca.min.x!==ca.max.x&&(e=j)):(j=d||m>0)&&_b()>1?(g=l,m>0&&lf.currItem.fitRatio&&(oa[a]+=b[a]*c)):(void 0!==g&&(Ja(g,!0),Z=g===mb.x?!1:!0),ca.min.x!==ca.max.x&&(void 0!==e?oa.x=e:Z||(oa.x+=b.x*c)),void 0!==g)},Nb=function(a){if(!("mousedown"===a.type&&a.button>0)){if(Zb)return void a.preventDefault();if(!T||"mousedown"!==a.type){if(Db(a,!0)&&a.preventDefault(),Ca("pointerDown"),F){var b=e.arraySearch(lb,a.pointerId,"id");0>b&&(b=lb.length),lb[b]={x:a.pageX,y:a.pageY,id:a.pointerId}}var c=Lb(a),d=c.length;$=null,bb(),U&&1!==d||(U=ga=!0,e.bind(window,p,f),R=ja=ha=S=Z=X=V=W=!1,fa=null,Ca("firstTouchStart",c),La(na,oa),ma.x=ma.y=0,La(jb,c[0]),La(kb,jb),mb.x=sa.x*qa,nb=[{x:jb.x,y:jb.y}],P=O=Da(),Ra(s,!0),yb(),zb()),!_&&d>1&&!ea&&!Z&&(t=s,W=!1,_=V=!0,ma.y=ma.x=0,La(na,oa),La(gb,c[0]),La(hb,c[1]),Fb(gb,hb,ub),tb.x=Math.abs(ub.x)-oa.x,tb.y=Math.abs(ub.y)-oa.y,aa=ba=xb(gb,hb))}}},Ob=function(a){if(a.preventDefault(),F){var b=e.arraySearch(lb,a.pointerId,"id");if(b>-1){var c=lb[b];c.x=a.pageX,c.y=a.pageY}}if(U){var d=Lb(a);if(fa||X||_)$=d;else if(sb.x!==sa.x*qa)fa="h";else{var f=Math.abs(d[0].x-jb.x)-Math.abs(d[0].y-jb.y);Math.abs(f)>=fb&&(fa=f>0?"h":"v",$=d)}}},Pb=function(){if($){var a=$.length;if(0!==a)if(La(gb,$[0]),ib.x=gb.x-jb.x,ib.y=gb.y-jb.y,_&&a>1){if(jb.x=gb.x,jb.y=gb.y,!ib.x&&!ib.y&&vb($[1],hb))return;La(hb,$[1]),W||(W=!0,Ca("zoomGestureStarted"));var b=xb(gb,hb),c=Ub(b);c>f.currItem.initialZoomLevel+f.currItem.initialZoomLevel/15&&(ja=!0);var d=1,e=Sa(),g=Ta();if(e>c)if(i.pinchToClose&&!ja&&t<=f.currItem.initialZoomLevel){var h=e-c,j=1-h/(e/1.2);Ea(j),Ca("onPinchClose",j),ha=!0}else d=(e-c)/e,d>1&&(d=1),c=e-d*(e/3);else c>g&&(d=(c-g)/(6*e),d>1&&(d=1),c=g+d*e);0>d&&(d=0),aa=b,Fb(gb,hb,qb),ma.x+=qb.x-ub.x,ma.y+=qb.y-ub.y,La(ub,qb),oa.x=Ka("x",c),oa.y=Ka("y",c),R=c>s,s=c,Ga()}else{if(!fa)return;if(ga&&(ga=!1,Math.abs(ib.x)>=fb&&(ib.x-=$[0].x-kb.x),Math.abs(ib.y)>=fb&&(ib.y-=$[0].y-kb.y)),jb.x=gb.x,jb.y=gb.y,0===ib.x&&0===ib.y)return;if("v"===fa&&i.closeOnVerticalDrag&&!Ab()){ma.y+=ib.y,oa.y+=ib.y;var k=Hb();return S=!0,Ca("onVerticalDrag",k),Ea(k),void Ga()}Gb(Da(),gb.x,gb.y),X=!0,ca=f.currItem.bounds;var l=Mb("x",ib);l||(Mb("y",ib),Ma(oa),Ga())}}},Qb=function(a){if(N.isOldAndroid){if(T&&"mouseup"===a.type)return;a.type.indexOf("touch")>-1&&(clearTimeout(T),T=setTimeout(function(){T=0},600))}Ca("pointerUp"),Db(a,!1)&&a.preventDefault();var b;if(F){var c=e.arraySearch(lb,a.pointerId,"id");if(c>-1)if(b=lb.splice(c,1)[0],navigator.pointerEnabled)b.type=a.pointerType||"mouse";else{var d={4:"mouse",2:"touch",3:"pen"};b.type=d[a.pointerType],b.type||(b.type=a.pointerType||"mouse")}}var g,h=Lb(a),j=h.length;if("mouseup"===a.type&&(j=0),2===j)return $=null,!0;1===j&&La(kb,h[0]),0!==j||fa||ea||(b||("mouseup"===a.type?b={x:a.pageX,y:a.pageY,type:"mouse"}:a.changedTouches&&a.changedTouches[0]&&(b={x:a.changedTouches[0].pageX,y:a.changedTouches[0].pageY,type:"touch"})),Ca("touchRelease",a,b));var k=-1;if(0===j&&(U=!1,e.unbind(window,p,f),yb(),_?k=0:-1!==rb&&(k=Da()-rb)),rb=1===j?Da():-1,g=-1!==k&&150>k?"zoom":"swipe",_&&2>j&&(_=!1,1===j&&(g="zoomPointerUp"),Ca("zoomGestureEnded")),$=null,X||W||ea||S)if(bb(),Q||(Q=Rb()),Q.calculateSwipeSpeed("x"),S){var l=Hb();if(lf.currItem.fitRatio&&Sb(Q))}},Rb=function(){var a,b,c={lastFlickOffset:{},lastFlickDist:{},lastFlickSpeed:{},slowDownRatio:{},slowDownRatioReverse:{},speedDecelerationRatio:{},speedDecelerationRatioAbs:{},distanceOffset:{},backAnimDestination:{},backAnimStarted:{},calculateSwipeSpeed:function(d){nb.length>1?(a=Da()-P+50,b=nb[nb.length-2][d]):(a=Da()-O,b=kb[d]),c.lastFlickOffset[d]=jb[d]-b,c.lastFlickDist[d]=Math.abs(c.lastFlickOffset[d]),c.lastFlickDist[d]>20?c.lastFlickSpeed[d]=c.lastFlickOffset[d]/a:c.lastFlickSpeed[d]=0,Math.abs(c.lastFlickSpeed[d])<.1&&(c.lastFlickSpeed[d]=0),c.slowDownRatio[d]=.95,c.slowDownRatioReverse[d]=1-c.slowDownRatio[d],c.speedDecelerationRatio[d]=1},calculateOverBoundsAnimOffset:function(a,b){c.backAnimStarted[a]||(oa[a]>ca.min[a]?c.backAnimDestination[a]=ca.min[a]:oa[a]eb&&(h||b.lastFlickOffset.x>20)?d=-1:-eb>g&&(h||b.lastFlickOffset.x<-20)&&(d=1)}var j;d&&(m+=d,0>m?(m=i.loop?_b()-1:0,j=!0):m>=_b()&&(m=i.loop?0:_b()-1,j=!0),(!j||i.loop)&&(ta+=d,qa-=d,c=!0));var k,l=sa.x*qa,n=Math.abs(l-sb.x);return c||l>sb.x==b.lastFlickSpeed.x>0?(k=Math.abs(b.lastFlickSpeed.x)>0?n/Math.abs(b.lastFlickSpeed.x):333,k=Math.min(k,400),k=Math.max(k,250)):k=333,pb===m&&(c=!1),ea=!0,Ca("mainScrollAnimStart"),cb("mainScroll",sb.x,l,k,e.easing.cubic.out,Ja,function(){bb(),ea=!1,pb=-1,(c||pb!==m)&&f.updateCurrItem(),Ca("mainScrollAnimComplete")}),c&&f.updateCurrItem(!0),c},Ub=function(a){return 1/ba*a*t},Vb=function(){var a=s,b=Sa(),c=Ta();b>s?a=b:s>c&&(a=c);var d,g=1,h=ia;return ha&&!R&&!ja&&b>s?(f.close(),!0):(ha&&(d=function(a){Ea((g-h)*a+h)}),f.zoomTo(a,0,200,e.easing.cubic.out,d),!0)};ya("Gestures",{publicMethods:{initGestures:function(){var a=function(a,b,c,d,e){A=a+b,B=a+c,C=a+d,D=e?a+e:""};F=N.pointerEvent,F&&N.touch&&(N.touch=!1),F?navigator.pointerEnabled?a("pointer","down","move","up","cancel"):a("MSPointer","Down","Move","Up","Cancel"):N.touch?(a("touch","start","move","end","cancel"),G=!0):a("mouse","down","move","up"),p=B+" "+C+" "+D,q=A,F&&!G&&(G=navigator.maxTouchPoints>1||navigator.msMaxTouchPoints>1),f.likelyTouchDevice=G,r[A]=Nb,r[B]=Ob,r[C]=Qb,D&&(r[D]=r[C]),N.touch&&(q+=" mousedown",p+=" mousemove mouseup",r.mousedown=r[A],r.mousemove=r[B],r.mouseup=r[C]),G||(i.allowPanToNext=!1)}}});var Wb,Xb,Yb,Zb,$b,_b,ac,bc=function(b,c,d,g){Wb&&clearTimeout(Wb),Zb=!0,Yb=!0;var h;b.initialLayout?(h=b.initialLayout,b.initialLayout=null):h=i.getThumbBoundsFn&&i.getThumbBoundsFn(m);var j=d?i.hideAnimationDuration:i.showAnimationDuration,k=function(){_a("initialZoom"),d?(f.template.removeAttribute("style"),f.bg.removeAttribute("style")):(Ea(1),c&&(c.style.display="block"),e.addClass(a,"pswp--animated-in"),Ca("initialZoom"+(d?"OutEnd":"InEnd"))),g&&g(),Zb=!1};if(!j||!h||void 0===h.x)return Ca("initialZoom"+(d?"Out":"In")),s=b.initialZoomLevel,La(oa,b.initialPosition),Ga(),a.style.opacity=d?0:1,Ea(1),void(j?setTimeout(function(){k()},j):k());var n=function(){var c=l,g=!f.currItem.src||f.currItem.loadError||i.showHideOpacity;b.miniImg&&(b.miniImg.style.webkitBackfaceVisibility="hidden"),d||(s=h.w/b.w,oa.x=h.x,oa.y=h.y-K,f[g?"template":"bg"].style.opacity=.001,Ga()),ab("initialZoom"),d&&!c&&e.removeClass(a,"pswp--animated-in"),g&&(d?e[(c?"remove":"add")+"Class"](a,"pswp--animate_opacity"):setTimeout(function(){e.addClass(a,"pswp--animate_opacity")},30)),Wb=setTimeout(function(){if(Ca("initialZoom"+(d?"Out":"In")),d){var f=h.w/b.w,i={x:oa.x,y:oa.y},l=s,m=ia,n=function(b){1===b?(s=f,oa.x=h.x,oa.y=h.y-M):(s=(f-l)*b+l,oa.x=(h.x-i.x)*b+i.x,oa.y=(h.y-M-i.y)*b+i.y),Ga(),g?a.style.opacity=1-b:Ea(m-b*m)};c?cb("initialZoom",0,1,j,e.easing.cubic.out,n,k):(n(1),Wb=setTimeout(k,j+20))}else s=b.initialZoomLevel,La(oa,b.initialPosition),Ga(),Ea(1),g?a.style.opacity=1:Ea(1),Wb=setTimeout(k,j+20)},d?25:90)};n()},cc={},dc=[],ec={index:0,errorMsg:'',forceProgressiveLoading:!1,preload:[1,1],getNumItemsFn:function(){return Xb.length}},fc=function(){return{center:{x:0,y:0},max:{x:0,y:0},min:{x:0,y:0}}},gc=function(a,b,c){var d=a.bounds;d.center.x=Math.round((cc.x-b)/2),d.center.y=Math.round((cc.y-c)/2)+a.vGap.top,d.max.x=b>cc.x?Math.round(cc.x-b):d.center.x,d.max.y=c>cc.y?Math.round(cc.y-c)+a.vGap.top:d.center.y,d.min.x=b>cc.x?0:d.center.x,d.min.y=c>cc.y?a.vGap.top:d.center.y},hc=function(a,b,c){if(a.src&&!a.loadError){var d=!c;if(d&&(a.vGap||(a.vGap={top:0,bottom:0}),Ca("parseVerticalMargin",a)),cc.x=b.x,cc.y=b.y-a.vGap.top-a.vGap.bottom,d){var e=cc.x/a.w,f=cc.y/a.h;a.fitRatio=f>e?e:f;var g=i.scaleMode;"orig"===g?c=1:"fit"===g&&(c=a.fitRatio),c>1&&(c=1),a.initialZoomLevel=c,a.bounds||(a.bounds=fc())}if(!c)return;return gc(a,a.w*c,a.h*c),d&&c===a.initialZoomLevel&&(a.initialPosition=a.bounds.center),a.bounds}return a.w=a.h=0,a.initialZoomLevel=a.fitRatio=1,a.bounds=fc(),a.initialPosition=a.bounds.center,a.bounds},ic=function(a,b,c,d,e,g){b.loadError||d&&(b.imageAppended=!0,lc(b,d,b===f.currItem&&xa),c.appendChild(d),g&&setTimeout(function(){b&&b.loaded&&b.placeholder&&(b.placeholder.style.display="none",b.placeholder=null)},500))},jc=function(a){a.loading=!0,a.loaded=!1;var b=a.img=e.createEl("pswp__img","img"),c=function(){a.loading=!1,a.loaded=!0,a.loadComplete?a.loadComplete(a):a.img=null,b.onload=b.onerror=null,b=null};return b.onload=c,b.onerror=function(){a.loadError=!0,c()},b.src=a.src,b},kc=function(a,b){return a.src&&a.loadError&&a.container?(b&&(a.container.innerHTML=""),a.container.innerHTML=i.errorMsg.replace("%url%",a.src),!0):void 0},lc=function(a,b,c){if(a.src){b||(b=a.container.lastChild);var d=c?a.w:Math.round(a.w*a.fitRatio),e=c?a.h:Math.round(a.h*a.fitRatio);a.placeholder&&!a.loaded&&(a.placeholder.style.width=d+"px",a.placeholder.style.height=e+"px"),b.style.width=d+"px",b.style.height=e+"px"}},mc=function(){if(dc.length){for(var a,b=0;b=0,e=Math.min(c[0],_b()),g=Math.min(c[1],_b());for(b=1;(d?g:e)>=b;b++)f.lazyLoadItem(m+b);for(b=1;(d?e:g)>=b;b++)f.lazyLoadItem(m-b)}),Ba("initialLayout",function(){f.currItem.initialLayout=i.getThumbBoundsFn&&i.getThumbBoundsFn(m)}),Ba("mainScrollAnimComplete",mc),Ba("initialZoomInEnd",mc),Ba("destroy",function(){for(var a,b=0;b=0&&void 0!==Xb[a]?Xb[a]:!1},allowProgressiveImg:function(){return i.forceProgressiveLoading||!G||i.mouseUsed||screen.width>1200},setContent:function(a,b){i.loop&&(b=za(b));var c=f.getItemAt(a.index);c&&(c.container=null);var d,g=f.getItemAt(b);if(!g)return void(a.el.innerHTML="");Ca("gettingData",b,g),a.index=b,a.item=g;var h=g.container=e.createEl("pswp__zoom-wrap");if(!g.src&&g.html&&(g.html.tagName?h.appendChild(g.html):h.innerHTML=g.html),kc(g),hc(g,pa),!g.src||g.loadError||g.loaded)g.src&&!g.loadError&&(d=e.createEl("pswp__img","img"),d.style.opacity=1,d.src=g.src,lc(g,d),ic(b,g,h,d,!0));else{if(g.loadComplete=function(c){if(j){if(a&&a.index===b){if(kc(c,!0))return c.loadComplete=c.img=null,hc(c,pa),Ha(c),void(a.index===m&&f.updateCurrZoomItem());c.imageAppended?!Zb&&c.placeholder&&(c.placeholder.style.display="none",c.placeholder=null):N.transform&&(ea||Zb)?dc.push({item:c,baseDiv:h,img:c.img,index:b,holder:a,clearPlaceholder:!0}):ic(b,c,h,c.img,ea||Zb,!0)}c.loadComplete=null,c.img=null,Ca("imageLoadComplete",b,c)}},e.features.transform){var k="pswp__img pswp__img--placeholder";k+=g.msrc?"":" pswp__img--placeholder--blank";var l=e.createEl(k,g.msrc?"img":"");g.msrc&&(l.src=g.msrc),lc(g,l),h.appendChild(l),g.placeholder=l}g.loading||jc(g),f.allowProgressiveImg()&&(!Yb&&N.transform?dc.push({item:g,baseDiv:h,img:g.img,index:b,holder:a}):ic(b,g,h,g.img,!0,!0))}Yb||b!==m?Ha(g):(da=h.style,bc(g,d||g.img)),a.el.innerHTML="",a.el.appendChild(h)},cleanSlide:function(a){a.img&&(a.img.onload=a.img.onerror=null),a.loaded=a.loading=a.img=a.imageAppended=!1}}});var nc,oc={},pc=function(a,b,c){var d=document.createEvent("CustomEvent"),e={origEvent:a,target:a.target,releasePoint:b,pointerType:c||"touch"};d.initCustomEvent("pswpTap",!0,!0,e),a.target.dispatchEvent(d)};ya("Tap",{publicMethods:{initTap:function(){Ba("firstTouchStart",f.onTapStart),Ba("touchRelease",f.onTapRelease),Ba("destroy",function(){oc={},nc=null})},onTapStart:function(a){a.length>1&&(clearTimeout(nc),nc=null)},onTapRelease:function(a,b){if(b&&!X&&!V&&!$a){var c=b;if(nc&&(clearTimeout(nc),nc=null,wb(c,oc)))return void Ca("doubleTap",c);if("mouse"===b.type)return void pc(a,b,"mouse");var d=a.target.tagName.toUpperCase();if("BUTTON"===d||e.hasClass(a.target,"pswp__single-tap"))return void pc(a,b);La(oc,c),nc=setTimeout(function(){pc(a,b),nc=null},300)}}}});var qc;ya("DesktopZoom",{publicMethods:{initDesktopZoom:function(){L||(G?Ba("mouseUsed",function(){f.setupDesktopZoom()}):f.setupDesktopZoom(!0))},setupDesktopZoom:function(b){qc={};var c="wheel mousewheel DOMMouseScroll";Ba("bindEvents",function(){e.bind(a,c,f.handleMouseWheel)}),Ba("unbindEvents",function(){qc&&e.unbind(a,c,f.handleMouseWheel)}),f.mouseZoomedIn=!1;var d,g=function(){f.mouseZoomedIn&&(e.removeClass(a,"pswp--zoomed-in"),f.mouseZoomedIn=!1),1>s?e.addClass(a,"pswp--zoom-allowed"):e.removeClass(a,"pswp--zoom-allowed"),h()},h=function(){d&&(e.removeClass(a,"pswp--dragging"),d=!1)};Ba("resize",g),Ba("afterChange",g),Ba("pointerDown",function(){f.mouseZoomedIn&&(d=!0,e.addClass(a,"pswp--dragging"))}),Ba("pointerUp",h),b||g()},handleMouseWheel:function(a){if(s<=f.currItem.fitRatio)return i.modal&&(!i.closeOnScroll||$a||U?a.preventDefault():E&&Math.abs(a.deltaY)>2&&(l=!0,f.close())),!0;if(a.stopPropagation(),qc.x=0,"deltaX"in a)1===a.deltaMode?(qc.x=18*a.deltaX,qc.y=18*a.deltaY):(qc.x=a.deltaX,qc.y=a.deltaY);else if("wheelDelta"in a)a.wheelDeltaX&&(qc.x=-.16*a.wheelDeltaX),a.wheelDeltaY?qc.y=-.16*a.wheelDeltaY:qc.y=-.16*a.wheelDelta;else{if(!("detail"in a))return;qc.y=a.detail}Ra(s,!0);var b=oa.x-qc.x,c=oa.y-qc.y;(i.modal||b<=ca.min.x&&b>=ca.max.x&&c<=ca.min.y&&c>=ca.max.y)&&a.preventDefault(),f.panTo(b,c)},toggleDesktopZoom:function(b){b=b||{x:pa.x/2+ra.x,y:pa.y/2+ra.y};var c=i.getDoubleTapZoom(!0,f.currItem),d=s===c;f.mouseZoomedIn=!d,f.zoomTo(d?f.currItem.initialZoomLevel:c,b,333),e[(d?"remove":"add")+"Class"](a,"pswp--zoomed-in")}}});var rc,sc,tc,uc,vc,wc,xc,yc,zc,Ac,Bc,Cc,Dc={history:!0,galleryUID:1},Ec=function(){return Bc.hash.substring(1)},Fc=function(){rc&&clearTimeout(rc),tc&&clearTimeout(tc)},Gc=function(){var a=Ec(),b={};if(a.length<5)return b;var c,d=a.split("&");for(c=0;c-1&&(xc=xc.split("&gid=")[0],xc=xc.split("?gid=")[0]),Ba("afterChange",f.updateURL),Ba("unbindEvents",function(){e.unbind(window,"hashchange",f.onHashChange)});var a=function(){wc=!0,zc||(Ac?history.back():xc?Bc.hash=xc:Cc?history.pushState("",document.title,Bc.pathname+Bc.search):Bc.hash=""),Fc()};Ba("unbindEvents",function(){l&&a()}),Ba("destroy",function(){wc||a()}),Ba("firstUpdate",function(){m=Gc().pid});var b=xc.indexOf("pid=");b>-1&&(xc=xc.substring(0,b),"&"===xc.slice(-1)&&(xc=xc.slice(0,-1))),setTimeout(function(){j&&e.bind(window,"hashchange",f.onHashChange)},40)}},onHashChange:function(){return Ec()===xc?(zc=!0,void f.close()):void(uc||(vc=!0,f.goTo(Gc().pid),vc=!1))},updateURL:function(){Fc(),vc||(yc?rc=setTimeout(Hc,800):Hc())}}}),e.extend(f,db)};return a});
\ No newline at end of file
+* Copyright (c) 2017 Dmitry Semenov; */
+!function(a,b){"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():a.PhotoSwipe=b()}(this,function(){"use strict";var a=function(a,b,c,d){var e={features:null,bind:function(a,b,c,d){var e=(d?"remove":"add")+"EventListener";b=b.split(" ");for(var f=0;f0&&(g=parseInt(g[1],10),g>=1&&g<8&&(d.isOldIOSPhone=!0))}var h=f.match(/Android\s([0-9\.]*)/),i=h?h[1]:0;i=parseFloat(i),i>=1&&(i<4.4&&(d.isOldAndroid=!0),d.androidVersion=i),d.isMobileOpera=/opera mini|opera mobi/i.test(f)}for(var j,k,l=["transform","perspective","animationName"],m=["","webkit","Moz","ms","O"],n=0;n<4;n++){c=m[n];for(var o=0;o<3;o++)j=l[o],k=c+(c?j.charAt(0).toUpperCase()+j.slice(1):j),!d[j]&&k in b&&(d[j]=k);c&&!d.raf&&(c=c.toLowerCase(),d.raf=window[c+"RequestAnimationFrame"],d.raf&&(d.caf=window[c+"CancelAnimationFrame"]||window[c+"CancelRequestAnimationFrame"]))}if(!d.raf){var p=0;d.raf=function(a){var b=(new Date).getTime(),c=Math.max(0,16-(b-p)),d=window.setTimeout(function(){a(b+c)},c);return p=b+c,d},d.caf=function(a){clearTimeout(a)}}return d.svg=!!document.createElementNS&&!!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,e.features=d,d}};e.detectFeatures(),e.features.oldIE&&(e.bind=function(a,b,c,d){b=b.split(" ");for(var e,f=(d?"detach":"attach")+"Event",g=function(){c.handleEvent.call(c)},h=0;hb-1?a-b:a<0?b+a:a},Ba={},Ca=function(a,b){return Ba[a]||(Ba[a]=[]),Ba[a].push(b)},Da=function(a){var b=Ba[a];if(b){var c=Array.prototype.slice.call(arguments);c.shift();for(var d=0;df.currItem.fitRatio?ya||(mc(f.currItem,!1,!0),ya=!0):ya&&(mc(f.currItem),ya=!1)),Ga(ea,pa.x,pa.y,s))},Ia=function(a){a.container&&Ga(a.container.style,a.initialPosition.x,a.initialPosition.y,a.initialZoomLevel,a)},Ja=function(a,b){b[E]=u+a+"px, 0px"+v},Ka=function(a,b){if(!i.loop&&b){var c=m+(ta.x*ra-a)/ta.x,d=Math.round(a-tb.x);(c<0&&d>0||c>=ac()-1&&d<0)&&(a=tb.x+d*i.mainScrollEndFriction)}tb.x=a,Ja(a,n)},La=function(a,b){var c=ub[a]-sa[a];return oa[a]+na[a]+c-c*(b/t)},Ma=function(a,b){a.x=b.x,a.y=b.y,b.id&&(a.id=b.id)},Na=function(a){a.x=Math.round(a.x),a.y=Math.round(a.y)},Oa=null,Pa=function(){Oa&&(e.unbind(document,"mousemove",Pa),e.addClass(a,"pswp--has_mouse"),i.mouseUsed=!0,Da("mouseUsed")),Oa=setTimeout(function(){Oa=null},100)},Qa=function(){e.bind(document,"keydown",f),N.transform&&e.bind(f.scrollWrap,"click",f),i.mouseUsed||e.bind(document,"mousemove",Pa),e.bind(window,"resize scroll orientationchange",f),Da("bindEvents")},Ra=function(){e.unbind(window,"resize scroll orientationchange",f),e.unbind(window,"scroll",r.scroll),e.unbind(document,"keydown",f),e.unbind(document,"mousemove",Pa),N.transform&&e.unbind(f.scrollWrap,"click",f),V&&e.unbind(window,p,f),clearTimeout(O),Da("unbindEvents")},Sa=function(a,b){var c=ic(f.currItem,qa,a);return b&&(da=c),c},Ta=function(a){return a||(a=f.currItem),a.initialZoomLevel},Ua=function(a){return a||(a=f.currItem),a.w>0?i.maxSpreadZoom:1},Va=function(a,b,c,d){return d===f.currItem.initialZoomLevel?(c[a]=f.currItem.initialPosition[a],!0):(c[a]=La(a,d),c[a]>b.min[a]?(c[a]=b.min[a],!0):c[a]1?1:a.fitRatio,c=a.container.style,d=b*a.w,e=b*a.h;c.width=d+"px",c.height=e+"px",c.left=a.initialPosition.x+"px",c.top=a.initialPosition.y+"px"},Ha=function(){if(ea){var a=ea,b=f.currItem,c=b.fitRatio>1?1:b.fitRatio,d=c*b.w,e=c*b.h;a.width=d+"px",a.height=e+"px",a.left=pa.x+"px",a.top=pa.y+"px"}}},Xa=function(a){var b="";i.escKey&&27===a.keyCode?b="close":i.arrowKeys&&(37===a.keyCode?b="prev":39===a.keyCode&&(b="next")),b&&(a.ctrlKey||a.altKey||a.shiftKey||a.metaKey||(a.preventDefault?a.preventDefault():a.returnValue=!1,f[b]()))},Ya=function(a){a&&(Y||X||fa||T)&&(a.preventDefault(),a.stopPropagation())},Za=function(){f.setScrollOffset(0,e.getScrollY())},$a={},_a=0,ab=function(a){$a[a]&&($a[a].raf&&I($a[a].raf),_a--,delete $a[a])},bb=function(a){$a[a]&&ab(a),$a[a]||(_a++,$a[a]={})},cb=function(){for(var a in $a)$a.hasOwnProperty(a)&&ab(a)},db=function(a,b,c,d,e,f,g){var h,i=Ea();bb(a);var j=function(){if($a[a]){if(h=Ea()-i,h>=d)return ab(a),f(c),void(g&&g());f((c-b)*e(h/d)+b),$a[a].raf=H(j)}};j()},eb={shout:Da,listen:Ca,viewportSize:qa,options:i,isMainScrollAnimating:function(){return fa},getZoomLevel:function(){return s},getCurrentIndex:function(){return m},isDragging:function(){return V},isZooming:function(){return aa},setScrollOffset:function(a,b){sa.x=a,M=sa.y=b,Da("updateScrollOffset",sa)},applyZoomPan:function(a,b,c,d){pa.x=b,pa.y=c,s=a,Ha(d)},init:function(){if(!j&&!k){var c;f.framework=e,f.template=a,f.bg=e.getChildByClass(a,"pswp__bg"),J=a.className,j=!0,N=e.detectFeatures(),H=N.raf,I=N.caf,E=N.transform,L=N.oldIE,f.scrollWrap=e.getChildByClass(a,"pswp__scroll-wrap"),f.container=e.getChildByClass(f.scrollWrap,"pswp__container"),n=f.container.style,f.itemHolders=y=[{el:f.container.children[0],wrap:0,index:-1},{el:f.container.children[1],wrap:0,index:-1},{el:f.container.children[2],wrap:0,index:-1}],y[0].el.style.display=y[2].el.style.display="none",Wa(),r={resize:f.updateSize,orientationchange:function(){clearTimeout(O),O=setTimeout(function(){qa.x!==f.scrollWrap.clientWidth&&f.updateSize()},500)},scroll:Za,keydown:Xa,click:Ya};var d=N.isOldIOSPhone||N.isOldAndroid||N.isMobileOpera;for(N.animationName&&N.transform&&!d||(i.showAnimationDuration=i.hideAnimationDuration=0),c=0;c=ac())&&(m=0),f.currItem=_b(m),(N.isOldIOSPhone||N.isOldAndroid)&&(va=!1),a.setAttribute("aria-hidden","false"),i.modal&&(va?a.style.position="fixed":(a.style.position="absolute",a.style.top=e.getScrollY()+"px")),void 0===M&&(Da("initialLayout"),M=K=e.getScrollY());var l="pswp--open ";for(i.mainClass&&(l+=i.mainClass+" "),i.showHideOpacity&&(l+="pswp--animate_opacity "),l+=G?"pswp--touch":"pswp--notouch",l+=N.animationName?" pswp--css_animation":"",l+=N.svg?" pswp--svg":"",e.addClass(a,l),f.updateSize(),o=-1,ua=null,c=0;cda.min.x?a=da.min.x:ada.min.y?b=da.min.y:b=h&&(o+=ua+(ua>0?-h:h),c=h);for(var d=0;d0?(b=y.shift(),y[h-1]=b,o++,Ja((o+2)*ta.x,b.el.style),f.setContent(b,m-c+d+1+1)):(b=y.pop(),y.unshift(b),o--,Ja(o*ta.x,b.el.style),f.setContent(b,m+c-d-1-1));if(ea&&1===Math.abs(ua)){var e=_b(z);e.initialZoomLevel!==s&&(ic(e,qa),mc(e),Ia(e))}ua=0,f.updateCurrZoomItem(),z=m,Da("afterChange")}}},updateSize:function(b){if(!va&&i.modal){var c=e.getScrollY();if(M!==c&&(a.style.top=c+"px",M=c),!b&&xa.x===window.innerWidth&&xa.y===window.innerHeight)return;xa.x=window.innerWidth,xa.y=window.innerHeight,a.style.height=xa.y+"px"}if(qa.x=f.scrollWrap.clientWidth,qa.y=f.scrollWrap.clientHeight,Za(),ta.x=qa.x+Math.round(qa.x*i.spacing),ta.y=qa.y,Ka(ta.x*ra),Da("beforeResize"),void 0!==o){for(var d,g,j,k=0;k2&&(j=Aa(j)),g=_b(j),g&&(x||g.needsUpdate||!g.bounds)?(f.cleanSlide(g),f.setContent(d,j),1===k&&(f.currItem=g,f.updateCurrZoomItem(!0)),g.needsUpdate=!1):d.index===-1&&j>=0&&f.setContent(d,j),g&&g.container&&(ic(g,qa),mc(g),Ia(g));x=!1}t=s=f.currItem.initialZoomLevel,da=f.currItem.bounds,da&&(pa.x=da.center.x,pa.y=da.center.y,Ha(!0)),Da("resize")},zoomTo:function(a,b,c,d,f){b&&(t=s,ub.x=Math.abs(b.x)-pa.x,ub.y=Math.abs(b.y)-pa.y,Ma(oa,pa));var g=Sa(a,!1),h={};Va("x",g,h,a),Va("y",g,h,a);var i=s,j={x:pa.x,y:pa.y};Na(h);var k=function(b){1===b?(s=a,pa.x=h.x,pa.y=h.y):(s=(a-i)*b+i,pa.x=(h.x-j.x)*b+j.x,pa.y=(h.y-j.y)*b+j.y),f&&f(b),Ha(1===b)};c?db("customZoomTo",0,1,c,d||e.easing.sine.inOut,k):k(1)}},fb=30,gb=10,hb={},ib={},jb={},kb={},lb={},mb=[],nb={},ob=[],pb={},qb=0,rb=ma(),sb=0,tb=ma(),ub=ma(),vb=ma(),wb=function(a,b){return a.x===b.x&&a.y===b.y},xb=function(a,b){return Math.abs(a.x-b.x)-1)&&(b(a)?a:Cb(a.parentNode,b)))},Db={},Eb=function(a,b){return Db.prevent=!Cb(a.target,i.isClickableElement),Da("preventDragEvent",a,b,Db),Db.prevent},Fb=function(a,b){return b.x=a.pageX,b.y=a.pageY,b.id=a.identifier,b},Gb=function(a,b,c){c.x=.5*(a.x+b.x),c.y=.5*(a.y+b.y)},Hb=function(a,b,c){if(a-Q>50){var d=ob.length>2?ob.shift():{};d.x=b,d.y=c,ob.push(d),Q=a}},Ib=function(){var a=pa.y-f.currItem.initialPosition.y;return 1-Math.abs(a/(qa.y/2))},Jb={},Kb={},Lb=[],Mb=function(a){for(;Lb.length>0;)Lb.pop();return F?(la=0,mb.forEach(function(a){0===la?Lb[0]=a:1===la&&(Lb[1]=a),la++})):a.type.indexOf("touch")>-1?a.touches&&a.touches.length>0&&(Lb[0]=Fb(a.touches[0],Jb),a.touches.length>1&&(Lb[1]=Fb(a.touches[1],Kb))):(Jb.x=a.pageX,Jb.y=a.pageY,Jb.id="",Lb[0]=Jb),Lb},Nb=function(a,b){var c,d,e,g,h=0,j=pa[a]+b[a],k=b[a]>0,l=tb.x+b.x,m=tb.x-nb.x;return c=j>da.min[a]||jda.min[a]&&(c=i.panEndFriction,h=da.min[a]-j,d=da.min[a]-oa[a]),(d<=0||m<0)&&ac()>1?(g=l,m<0&&l>nb.x&&(g=nb.x)):da.min.x!==da.max.x&&(e=j)):(j0)&&ac()>1?(g=l,m>0&&lf.currItem.fitRatio&&(pa[a]+=b[a]*c)):(void 0!==g&&(Ka(g,!0),$=g!==nb.x),da.min.x!==da.max.x&&(void 0!==e?pa.x=e:$||(pa.x+=b.x*c)),void 0!==g)},Ob=function(a){if(!("mousedown"===a.type&&a.button>0)){if($b)return void a.preventDefault();if(!U||"mousedown"!==a.type){if(Eb(a,!0)&&a.preventDefault(),Da("pointerDown"),F){var b=e.arraySearch(mb,a.pointerId,"id");b<0&&(b=mb.length),mb[b]={x:a.pageX,y:a.pageY,id:a.pointerId}}var c=Mb(a),d=c.length;_=null,cb(),V&&1!==d||(V=ha=!0,e.bind(window,p,f),S=ka=ia=T=$=Y=W=X=!1,ga=null,Da("firstTouchStart",c),Ma(oa,pa),na.x=na.y=0,Ma(kb,c[0]),Ma(lb,kb),nb.x=ta.x*ra,ob=[{x:kb.x,y:kb.y}],Q=P=Ea(),Sa(s,!0),zb(),Ab()),!aa&&d>1&&!fa&&!$&&(t=s,X=!1,aa=W=!0,na.y=na.x=0,Ma(oa,pa),Ma(hb,c[0]),Ma(ib,c[1]),Gb(hb,ib,vb),ub.x=Math.abs(vb.x)-pa.x,ub.y=Math.abs(vb.y)-pa.y,ba=ca=yb(hb,ib))}}},Pb=function(a){if(a.preventDefault(),F){var b=e.arraySearch(mb,a.pointerId,"id");if(b>-1){var c=mb[b];c.x=a.pageX,c.y=a.pageY}}if(V){var d=Mb(a);if(ga||Y||aa)_=d;else if(tb.x!==ta.x*ra)ga="h";else{var f=Math.abs(d[0].x-kb.x)-Math.abs(d[0].y-kb.y);Math.abs(f)>=gb&&(ga=f>0?"h":"v",_=d)}}},Qb=function(){if(_){var a=_.length;if(0!==a)if(Ma(hb,_[0]),jb.x=hb.x-kb.x,jb.y=hb.y-kb.y,aa&&a>1){if(kb.x=hb.x,kb.y=hb.y,!jb.x&&!jb.y&&wb(_[1],ib))return;Ma(ib,_[1]),X||(X=!0,Da("zoomGestureStarted"));var b=yb(hb,ib),c=Vb(b);c>f.currItem.initialZoomLevel+f.currItem.initialZoomLevel/15&&(ka=!0);var d=1,e=Ta(),g=Ua();if(c1&&(d=1),c=e-d*(e/3);else c>g&&(d=(c-g)/(6*e),d>1&&(d=1),c=g+d*e);d<0&&(d=0),ba=b,Gb(hb,ib,rb),na.x+=rb.x-vb.x,na.y+=rb.y-vb.y,Ma(vb,rb),pa.x=La("x",c),pa.y=La("y",c),S=c>s,s=c,Ha()}else{if(!ga)return;if(ha&&(ha=!1,Math.abs(jb.x)>=gb&&(jb.x-=_[0].x-lb.x),Math.abs(jb.y)>=gb&&(jb.y-=_[0].y-lb.y)),kb.x=hb.x,kb.y=hb.y,0===jb.x&&0===jb.y)return;if("v"===ga&&i.closeOnVerticalDrag&&!Bb()){na.y+=jb.y,pa.y+=jb.y;var k=Ib();return T=!0,Da("onVerticalDrag",k),Fa(k),void Ha()}Hb(Ea(),hb.x,hb.y),Y=!0,da=f.currItem.bounds;var l=Nb("x",jb);l||(Nb("y",jb),Na(pa),Ha())}}},Rb=function(a){if(N.isOldAndroid){if(U&&"mouseup"===a.type)return;a.type.indexOf("touch")>-1&&(clearTimeout(U),U=setTimeout(function(){U=0},600))}Da("pointerUp"),Eb(a,!1)&&a.preventDefault();var b;if(F){var c=e.arraySearch(mb,a.pointerId,"id");if(c>-1)if(b=mb.splice(c,1)[0],navigator.pointerEnabled)b.type=a.pointerType||"mouse";else{var d={4:"mouse",2:"touch",3:"pen"};b.type=d[a.pointerType],b.type||(b.type=a.pointerType||"mouse")}}var g,h=Mb(a),j=h.length;if("mouseup"===a.type&&(j=0),2===j)return _=null,!0;1===j&&Ma(lb,h[0]),0!==j||ga||fa||(b||("mouseup"===a.type?b={x:a.pageX,y:a.pageY,type:"mouse"}:a.changedTouches&&a.changedTouches[0]&&(b={x:a.changedTouches[0].pageX,y:a.changedTouches[0].pageY,type:"touch"})),Da("touchRelease",a,b));var k=-1;if(0===j&&(V=!1,e.unbind(window,p,f),zb(),aa?k=0:sb!==-1&&(k=Ea()-sb)),sb=1===j?Ea():-1,g=k!==-1&&k<150?"zoom":"swipe",aa&&j<2&&(aa=!1,1===j&&(g="zoomPointerUp"),Da("zoomGestureEnded")),_=null,Y||X||fa||T)if(cb(),R||(R=Sb()),R.calculateSwipeSpeed("x"),T){var l=Ib();if(lf.currItem.fitRatio&&Tb(R))}},Sb=function(){var a,b,c={lastFlickOffset:{},lastFlickDist:{},lastFlickSpeed:{},slowDownRatio:{},slowDownRatioReverse:{},speedDecelerationRatio:{},speedDecelerationRatioAbs:{},distanceOffset:{},backAnimDestination:{},backAnimStarted:{},calculateSwipeSpeed:function(d){ob.length>1?(a=Ea()-Q+50,b=ob[ob.length-2][d]):(a=Ea()-P,b=lb[d]),c.lastFlickOffset[d]=kb[d]-b,c.lastFlickDist[d]=Math.abs(c.lastFlickOffset[d]),c.lastFlickDist[d]>20?c.lastFlickSpeed[d]=c.lastFlickOffset[d]/a:c.lastFlickSpeed[d]=0,Math.abs(c.lastFlickSpeed[d])<.1&&(c.lastFlickSpeed[d]=0),c.slowDownRatio[d]=.95,c.slowDownRatioReverse[d]=1-c.slowDownRatio[d],c.speedDecelerationRatio[d]=1},calculateOverBoundsAnimOffset:function(a,b){c.backAnimStarted[a]||(pa[a]>da.min[a]?c.backAnimDestination[a]=da.min[a]:pa[a]fb&&(h||b.lastFlickOffset.x>20)?d=-1:g<-fb&&(h||b.lastFlickOffset.x<-20)&&(d=1)}var j;d&&(m+=d,m<0?(m=i.loop?ac()-1:0,j=!0):m>=ac()&&(m=i.loop?0:ac()-1,j=!0),j&&!i.loop||(ua+=d,ra-=d,c=!0));var k,l=ta.x*ra,n=Math.abs(l-tb.x);return c||l>tb.x==b.lastFlickSpeed.x>0?(k=Math.abs(b.lastFlickSpeed.x)>0?n/Math.abs(b.lastFlickSpeed.x):333,k=Math.min(k,400),k=Math.max(k,250)):k=333,qb===m&&(c=!1),fa=!0,Da("mainScrollAnimStart"),db("mainScroll",tb.x,l,k,e.easing.cubic.out,Ka,function(){cb(),fa=!1,qb=-1,(c||qb!==m)&&f.updateCurrItem(),Da("mainScrollAnimComplete")}),c&&f.updateCurrItem(!0),c},Vb=function(a){return 1/ca*a*t},Wb=function(){var a=s,b=Ta(),c=Ua();sc&&(a=c);var d,g=1,h=ja;return ia&&!S&&!ka&&s1||navigator.msMaxTouchPoints>1),f.likelyTouchDevice=G,r[A]=Ob,r[B]=Pb,r[C]=Rb,D&&(r[D]=r[C]),N.touch&&(q+=" mousedown",p+=" mousemove mouseup",r.mousedown=r[A],r.mousemove=r[B],r.mouseup=r[C]),G||(i.allowPanToNext=!1)}}});var Xb,Yb,Zb,$b,_b,ac,bc,cc=function(b,c,d,g){Xb&&clearTimeout(Xb),$b=!0,Zb=!0;var h;b.initialLayout?(h=b.initialLayout,b.initialLayout=null):h=i.getThumbBoundsFn&&i.getThumbBoundsFn(m);var j=d?i.hideAnimationDuration:i.showAnimationDuration,k=function(){ab("initialZoom"),d?(f.template.removeAttribute("style"),f.bg.removeAttribute("style")):(Fa(1),c&&(c.style.display="block"),e.addClass(a,"pswp--animated-in"),Da("initialZoom"+(d?"OutEnd":"InEnd"))),g&&g(),$b=!1};if(!j||!h||void 0===h.x)return Da("initialZoom"+(d?"Out":"In")),s=b.initialZoomLevel,Ma(pa,b.initialPosition),Ha(),a.style.opacity=d?0:1,Fa(1),void(j?setTimeout(function(){k()},j):k());var n=function(){var c=l,g=!f.currItem.src||f.currItem.loadError||i.showHideOpacity;b.miniImg&&(b.miniImg.style.webkitBackfaceVisibility="hidden"),d||(s=h.w/b.w,pa.x=h.x,pa.y=h.y-K,f[g?"template":"bg"].style.opacity=.001,Ha()),bb("initialZoom"),d&&!c&&e.removeClass(a,"pswp--animated-in"),g&&(d?e[(c?"remove":"add")+"Class"](a,"pswp--animate_opacity"):setTimeout(function(){e.addClass(a,"pswp--animate_opacity")},30)),Xb=setTimeout(function(){if(Da("initialZoom"+(d?"Out":"In")),d){var f=h.w/b.w,i={x:pa.x,y:pa.y},l=s,m=ja,n=function(b){1===b?(s=f,pa.x=h.x,pa.y=h.y-M):(s=(f-l)*b+l,pa.x=(h.x-i.x)*b+i.x,pa.y=(h.y-M-i.y)*b+i.y),Ha(),g?a.style.opacity=1-b:Fa(m-b*m)};c?db("initialZoom",0,1,j,e.easing.cubic.out,n,k):(n(1),Xb=setTimeout(k,j+20))}else s=b.initialZoomLevel,Ma(pa,b.initialPosition),Ha(),Fa(1),g?a.style.opacity=1:Fa(1),Xb=setTimeout(k,j+20)},d?25:90)};n()},dc={},ec=[],fc={index:0,errorMsg:'',forceProgressiveLoading:!1,preload:[1,1],getNumItemsFn:function(){return Yb.length}},gc=function(){return{center:{x:0,y:0},max:{x:0,y:0},min:{x:0,y:0}}},hc=function(a,b,c){var d=a.bounds;d.center.x=Math.round((dc.x-b)/2),d.center.y=Math.round((dc.y-c)/2)+a.vGap.top,d.max.x=b>dc.x?Math.round(dc.x-b):d.center.x,d.max.y=c>dc.y?Math.round(dc.y-c)+a.vGap.top:d.center.y,d.min.x=b>dc.x?0:d.center.x,d.min.y=c>dc.y?a.vGap.top:d.center.y},ic=function(a,b,c){if(a.src&&!a.loadError){var d=!c;if(d&&(a.vGap||(a.vGap={top:0,bottom:0}),Da("parseVerticalMargin",a)),dc.x=b.x,dc.y=b.y-a.vGap.top-a.vGap.bottom,d){var e=dc.x/a.w,f=dc.y/a.h;a.fitRatio=e1&&(c=1),a.initialZoomLevel=c,a.bounds||(a.bounds=gc())}if(!c)return;return hc(a,a.w*c,a.h*c),d&&c===a.initialZoomLevel&&(a.initialPosition=a.bounds.center),a.bounds}return a.w=a.h=0,a.initialZoomLevel=a.fitRatio=1,a.bounds=gc(),a.initialPosition=a.bounds.center,a.bounds},jc=function(a,b,c,d,e,g){b.loadError||d&&(b.imageAppended=!0,mc(b,d,b===f.currItem&&ya),c.appendChild(d),g&&setTimeout(function(){b&&b.loaded&&b.placeholder&&(b.placeholder.style.display="none",b.placeholder=null)},500))},kc=function(a){a.loading=!0,a.loaded=!1;var b=a.img=e.createEl("pswp__img","img"),c=function(){a.loading=!1,a.loaded=!0,a.loadComplete?a.loadComplete(a):a.img=null,b.onload=b.onerror=null,b=null};return b.onload=c,b.onerror=function(){a.loadError=!0,c()},b.src=a.src,b},lc=function(a,b){if(a.src&&a.loadError&&a.container)return b&&(a.container.innerHTML=""),a.container.innerHTML=i.errorMsg.replace("%url%",a.src),!0},mc=function(a,b,c){if(a.src){b||(b=a.container.lastChild);var d=c?a.w:Math.round(a.w*a.fitRatio),e=c?a.h:Math.round(a.h*a.fitRatio);a.placeholder&&!a.loaded&&(a.placeholder.style.width=d+"px",a.placeholder.style.height=e+"px"),b.style.width=d+"px",b.style.height=e+"px"}},nc=function(){if(ec.length){for(var a,b=0;b=0,e=Math.min(c[0],ac()),g=Math.min(c[1],ac());for(b=1;b<=(d?g:e);b++)f.lazyLoadItem(m+b);for(b=1;b<=(d?e:g);b++)f.lazyLoadItem(m-b)}),Ca("initialLayout",function(){f.currItem.initialLayout=i.getThumbBoundsFn&&i.getThumbBoundsFn(m)}),Ca("mainScrollAnimComplete",nc),Ca("initialZoomInEnd",nc),Ca("destroy",function(){for(var a,b=0;b=0&&(void 0!==Yb[a]&&Yb[a])},allowProgressiveImg:function(){return i.forceProgressiveLoading||!G||i.mouseUsed||screen.width>1200},setContent:function(a,b){i.loop&&(b=Aa(b));var c=f.getItemAt(a.index);c&&(c.container=null);var d,g=f.getItemAt(b);if(!g)return void(a.el.innerHTML="");Da("gettingData",b,g),a.index=b,a.item=g;var h=g.container=e.createEl("pswp__zoom-wrap");if(!g.src&&g.html&&(g.html.tagName?h.appendChild(g.html):h.innerHTML=g.html),lc(g),ic(g,qa),!g.src||g.loadError||g.loaded)g.src&&!g.loadError&&(d=e.createEl("pswp__img","img"),d.style.opacity=1,d.src=g.src,mc(g,d),jc(b,g,h,d,!0));else{if(g.loadComplete=function(c){if(j){if(a&&a.index===b){if(lc(c,!0))return c.loadComplete=c.img=null,ic(c,qa),Ia(c),void(a.index===m&&f.updateCurrZoomItem());c.imageAppended?!$b&&c.placeholder&&(c.placeholder.style.display="none",c.placeholder=null):N.transform&&(fa||$b)?ec.push({item:c,baseDiv:h,img:c.img,index:b,holder:a,clearPlaceholder:!0}):jc(b,c,h,c.img,fa||$b,!0)}c.loadComplete=null,c.img=null,Da("imageLoadComplete",b,c)}},e.features.transform){var k="pswp__img pswp__img--placeholder";k+=g.msrc?"":" pswp__img--placeholder--blank";var l=e.createEl(k,g.msrc?"img":"");g.msrc&&(l.src=g.msrc),mc(g,l),h.appendChild(l),g.placeholder=l}g.loading||kc(g),f.allowProgressiveImg()&&(!Zb&&N.transform?ec.push({item:g,baseDiv:h,img:g.img,index:b,holder:a}):jc(b,g,h,g.img,!0,!0))}Zb||b!==m?Ia(g):(ea=h.style,cc(g,d||g.img)),a.el.innerHTML="",a.el.appendChild(h)},cleanSlide:function(a){a.img&&(a.img.onload=a.img.onerror=null),a.loaded=a.loading=a.img=a.imageAppended=!1}}});var oc,pc={},qc=function(a,b,c){var d=document.createEvent("CustomEvent"),e={origEvent:a,target:a.target,releasePoint:b,pointerType:c||"touch"};d.initCustomEvent("pswpTap",!0,!0,e),a.target.dispatchEvent(d)};za("Tap",{publicMethods:{initTap:function(){Ca("firstTouchStart",f.onTapStart),Ca("touchRelease",f.onTapRelease),Ca("destroy",function(){pc={},oc=null})},onTapStart:function(a){a.length>1&&(clearTimeout(oc),oc=null)},onTapRelease:function(a,b){if(b&&!Y&&!W&&!_a){var c=b;if(oc&&(clearTimeout(oc),oc=null,xb(c,pc)))return void Da("doubleTap",c);if("mouse"===b.type)return void qc(a,b,"mouse");var d=a.target.tagName.toUpperCase();if("BUTTON"===d||e.hasClass(a.target,"pswp__single-tap"))return void qc(a,b);Ma(pc,c),oc=setTimeout(function(){qc(a,b),oc=null},300)}}}});var rc;za("DesktopZoom",{publicMethods:{initDesktopZoom:function(){L||(G?Ca("mouseUsed",function(){f.setupDesktopZoom()}):f.setupDesktopZoom(!0))},setupDesktopZoom:function(b){rc={};var c="wheel mousewheel DOMMouseScroll";Ca("bindEvents",function(){e.bind(a,c,f.handleMouseWheel)}),Ca("unbindEvents",function(){rc&&e.unbind(a,c,f.handleMouseWheel)}),f.mouseZoomedIn=!1;var d,g=function(){f.mouseZoomedIn&&(e.removeClass(a,"pswp--zoomed-in"),f.mouseZoomedIn=!1),s<1?e.addClass(a,"pswp--zoom-allowed"):e.removeClass(a,"pswp--zoom-allowed"),h()},h=function(){d&&(e.removeClass(a,"pswp--dragging"),d=!1)};Ca("resize",g),Ca("afterChange",g),Ca("pointerDown",function(){f.mouseZoomedIn&&(d=!0,e.addClass(a,"pswp--dragging"))}),Ca("pointerUp",h),b||g()},handleMouseWheel:function(a){if(s<=f.currItem.fitRatio)return i.modal&&(!i.closeOnScroll||_a||V?a.preventDefault():E&&Math.abs(a.deltaY)>2&&(l=!0,f.close())),!0;if(a.stopPropagation(),rc.x=0,"deltaX"in a)1===a.deltaMode?(rc.x=18*a.deltaX,rc.y=18*a.deltaY):(rc.x=a.deltaX,rc.y=a.deltaY);else if("wheelDelta"in a)a.wheelDeltaX&&(rc.x=-.16*a.wheelDeltaX),a.wheelDeltaY?rc.y=-.16*a.wheelDeltaY:rc.y=-.16*a.wheelDelta;else{if(!("detail"in a))return;rc.y=a.detail}Sa(s,!0);var b=pa.x-rc.x,c=pa.y-rc.y;(i.modal||b<=da.min.x&&b>=da.max.x&&c<=da.min.y&&c>=da.max.y)&&a.preventDefault(),f.panTo(b,c)},toggleDesktopZoom:function(b){b=b||{x:qa.x/2+sa.x,y:qa.y/2+sa.y};var c=i.getDoubleTapZoom(!0,f.currItem),d=s===c;f.mouseZoomedIn=!d,f.zoomTo(d?f.currItem.initialZoomLevel:c,b,333),e[(d?"remove":"add")+"Class"](a,"pswp--zoomed-in")}}});var sc,tc,uc,vc,wc,xc,yc,zc,Ac,Bc,Cc,Dc,Ec={history:!0,galleryUID:1},Fc=function(){return Cc.hash.substring(1)},Gc=function(){sc&&clearTimeout(sc),uc&&clearTimeout(uc)},Hc=function(){var a=Fc(),b={};if(a.length<5)return b;var c,d=a.split("&");for(c=0;c-1&&(yc=yc.split("&gid=")[0],yc=yc.split("?gid=")[0]),Ca("afterChange",f.updateURL),Ca("unbindEvents",function(){e.unbind(window,"hashchange",f.onHashChange)});var a=function(){xc=!0,Ac||(Bc?history.back():yc?Cc.hash=yc:Dc?history.pushState("",document.title,Cc.pathname+Cc.search):Cc.hash=""),Gc()};Ca("unbindEvents",function(){l&&a()}),Ca("destroy",function(){xc||a()}),Ca("firstUpdate",function(){m=Hc().pid});var b=yc.indexOf("pid=");b>-1&&(yc=yc.substring(0,b),"&"===yc.slice(-1)&&(yc=yc.slice(0,-1))),setTimeout(function(){j&&e.bind(window,"hashchange",f.onHashChange)},40)}},onHashChange:function(){return Fc()===yc?(Ac=!0,void f.close()):void(vc||(wc=!0,f.goTo(Hc().pid),wc=!1))},updateURL:function(){Gc(),wc||(zc?sc=setTimeout(Ic,800):Ic())}}}),e.extend(f,eb)};return a});
\ No newline at end of file
diff --git a/sigal/themes/photoswipe/static/styles.css b/sigal/themes/photoswipe/static/styles.css
index 77ba23d..edd709a 100644
--- a/sigal/themes/photoswipe/static/styles.css
+++ b/sigal/themes/photoswipe/static/styles.css
@@ -127,6 +127,9 @@ figcaption {
.album_title {
display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
}
.video {
@@ -181,6 +184,7 @@ figcaption {
.gallery__img--secondary {
width: 25%;
float:left;
+ margin-bottom: 1em;
}
.gallery__title {
diff --git a/sigal/themes/photoswipe/static/styles.min.css b/sigal/themes/photoswipe/static/styles.min.css
deleted file mode 100644
index 76928de..0000000
--- a/sigal/themes/photoswipe/static/styles.min.css
+++ /dev/null
@@ -1 +0,0 @@
-html,body,div,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,ol,ul,li,form,fieldset,legend,label,table,header,footer,nav,section,figure{margin:0;padding:0}body{background:#EEE;font-family:"myriad-pro","Myriad Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:18px;line-height:26px;color:#282B30;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-moz-font-feature-settings:"liga","kern"}figure{display:block;max-width:100%}a{color:#3169B3}a:hover{color:#C00}img{width:auto;max-width:100%;height:auto;border:0}p{margin:0 0 12px}ul{list-style:disc}ul,ol{padding:0;margin:0 0 12px 25px}li{margin:0 0 12px 0}h2,h3,h4,h5,h6{margin:0;font-weight:normal}h1{font-size:48px;line-height:1;margin:1em;font-weight:600;text-align:center}h1 a{text-decoration:none;color:#282B30}strong{font-weight:600}figcaption{display:none}.container{width:100%}.content{max-width:1024px;margin:24px auto;padding:2em 0}.menu{width:100%;background:#F7F7F7 none repeat scroll 0 0;padding:30px 0}.menu ul{max-width:1024px;margin:0 auto}.menu li{display:inline;list-style:none}.album-list{width:100%;padding:2em 0;margin:auto;background:#EEE none repeat scroll 0 0;float:left}.thumbnail{text-align:center;float:left}.thumbnail img{max-width:85%;height:auto;margin:0 2px 5px 2px;border:10px solid #fff;border-radius:2px 2px 2px 2px;box-shadow:0 0 3px #B1B1B1;padding:0 0 2px}.thumbnail img:hover{box-shadow:0 0 5px #818181}.album_title{display:block}.video{width:100%;margin:0 0 24px 0}.video__container{position:relative;width:100%;padding-bottom:56.25%;padding-top:35px;height:0;overflow:hidden}.video__container iframe,.video__container video{position:absolute;top:0;left:0;width:100%;height:100%;padding:2% 0 15% 0}.video-desc{width:100%;max-width:740px;margin:12px auto}.additionnal-infos{width:100%;height:auto;float:left}.gallery{width:100%;height:auto;float:left;padding-top:1em}.gallery a{line-height:0}.gallery__img--main a{width:auto;height:auto}.menu-img,.gallery__img--secondary{width:25%;float:left}.gallery__title{line-height:14px;font-size:14px;opacity:.8;margin-top:5px;width:100%;float:left}footer{width:100%;float:left}footer p{text-align:center}@media screen and (max-width:700px){h1{font-size:40px}.menu-img,.gallery__img--secondary{width:33%}}@media screen and (max-width:500px){.menu-img,.gallery__img--secondary{width:50%}}@media screen and (max-width:300px){.menu-img,.gallery__img--secondary{width:100%}}/*!PhotoSwipe Default UI CSS by Dmitry Semenov | photoswipe.com | MIT license */ .pswp__button{width:44px;height:44px;position:relative;background:none;cursor:pointer;overflow:visible;-webkit-appearance:none;display:block;border:0;padding:0;margin:0;float:right;opacity:.75;-webkit-transition:opacity .2s;transition:opacity .2s;-webkit-box-shadow:none;box-shadow:none}.pswp__button:focus,.pswp__button:hover{opacity:1}.pswp__button:active{outline:none;opacity:.9}.pswp__button::-moz-focus-inner{padding:0;border:0}.pswp__ui--over-close .pswp__button--close{opacity:1}.pswp__button,.pswp__button--arrow--left:before,.pswp__button--arrow--right:before{background:url(default-skin/default-skin.png) 0 0 no-repeat;background-size:264px 88px;width:44px;height:44px}@media(-webkit-min-device-pixel-ratio:1.1),(-webkit-min-device-pixel-ratio:1.09375),(min-resolution:105dpi),(min-resolution:1.1dppx){.pswp--svg .pswp__button,.pswp--svg .pswp__button--arrow--left:before,.pswp--svg .pswp__button--arrow--right:before{background-image:url(default-skin/default-skin.svg)}.pswp--svg .pswp__button--arrow--left,.pswp--svg .pswp__button--arrow--right{background:none}}.pswp__button--close{background-position:0 -44px}.pswp__button--share{background-position:-44px -44px}.pswp__button--fs{display:none}.pswp--supports-fs .pswp__button--fs{display:block}.pswp--fs .pswp__button--fs{background-position:-44px 0}.pswp__button--zoom{display:none;background-position:-88px 0}.pswp--zoom-allowed .pswp__button--zoom{display:block}.pswp--zoomed-in .pswp__button--zoom{background-position:-132px 0}.pswp--touch .pswp__button--arrow--left,.pswp--touch .pswp__button--arrow--right{visibility:hidden}.pswp__button--arrow--left,.pswp__button--arrow--right{background:none;top:50%;margin-top:-50px;width:70px;height:100px;position:absolute}.pswp__button--arrow--left{left:0}.pswp__button--arrow--right{right:0}.pswp__button--arrow--left:before,.pswp__button--arrow--right:before{content:'';top:35px;background-color:rgba(0,0,0,0.3);height:30px;width:32px;position:absolute}.pswp__button--arrow--left:before{left:6px;background-position:-138px -44px}.pswp__button--arrow--right:before{right:6px;background-position:-94px -44px}.pswp__counter,.pswp__share-modal{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pswp__share-modal{display:block;background:rgba(0,0,0,0.5);width:100%;height:100%;top:0;left:0;padding:10px;position:absolute;z-index:1600;opacity:0;-webkit-transition:opacity .25s ease-out;transition:opacity .25s ease-out;-webkit-backface-visibility:hidden;will-change:opacity}.pswp__share-modal--hidden{display:none}.pswp__share-tooltip{z-index:1620;position:absolute;background:#FFF;top:56px;border-radius:2px;display:block;width:auto;right:44px;-webkit-box-shadow:0 2px 5px rgba(0,0,0,0.25);box-shadow:0 2px 5px rgba(0,0,0,0.25);-webkit-transform:translateY(6px);-ms-transform:translateY(6px);transform:translateY(6px);-webkit-transition:-webkit-transform .25s;transition:transform .25s;-webkit-backface-visibility:hidden;will-change:transform}.pswp__share-tooltip a{display:block;padding:8px 12px;color:#000;text-decoration:none;font-size:14px;line-height:18px}.pswp__share-tooltip a:hover{text-decoration:none;color:#000}.pswp__share-tooltip a:first-child{border-radius:2px 2px 0 0}.pswp__share-tooltip a:last-child{border-radius:0 0 2px 2px}.pswp__share-modal--fade-in{opacity:1}.pswp__share-modal--fade-in .pswp__share-tooltip{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.pswp--touch .pswp__share-tooltip a{padding:16px 12px}a.pswp__share--facebook:before{content:'';display:block;width:0;height:0;position:absolute;top:-12px;right:15px;border:6px solid transparent;border-bottom-color:#FFF;-webkit-pointer-events:none;-moz-pointer-events:none;pointer-events:none}a.pswp__share--facebook:hover{background:#3E5C9A;color:#FFF}a.pswp__share--facebook:hover:before{border-bottom-color:#3E5C9A}a.pswp__share--twitter:hover{background:#55ACEE;color:#FFF}a.pswp__share--pinterest:hover{background:#CCC;color:#CE272D}a.pswp__share--download:hover{background:#DDD}.pswp__counter{position:absolute;left:0;top:0;height:44px;font-size:13px;line-height:44px;color:#FFF;opacity:.75;padding:0 10px}.pswp__caption{position:absolute;left:0;bottom:0;width:100%;min-height:44px}.pswp__caption small{font-size:11px;color:#BBB}.pswp__caption__center{text-align:left;max-width:420px;margin:0 auto;font-size:13px;padding:10px;line-height:20px;color:#CCC}.pswp__caption--empty{display:none}.pswp__caption--fake{visibility:hidden}.pswp__preloader{width:44px;height:44px;position:absolute;top:0;left:50%;margin-left:-22px;opacity:0;-webkit-transition:opacity .25s ease-out;transition:opacity .25s ease-out;will-change:opacity;direction:ltr}.pswp__preloader__icn{width:20px;height:20px;margin:12px}.pswp__preloader--active{opacity:1}.pswp__preloader--active .pswp__preloader__icn{background:url(preloader.gif) 0 0 no-repeat}.pswp--css_animation .pswp__preloader--active{opacity:1}.pswp--css_animation .pswp__preloader--active .pswp__preloader__icn{-webkit-animation:clockwise 500ms linear infinite;animation:clockwise 500ms linear infinite}.pswp--css_animation .pswp__preloader--active .pswp__preloader__donut{-webkit-animation:donut-rotate 1000ms cubic-bezier(0.4,0,0.22,1) infinite;animation:donut-rotate 1000ms cubic-bezier(0.4,0,0.22,1) infinite}.pswp--css_animation .pswp__preloader__icn{background:none;opacity:.75;width:14px;height:14px;position:absolute;left:15px;top:15px;margin:0}.pswp--css_animation .pswp__preloader__cut{position:relative;width:7px;height:14px;overflow:hidden}.pswp--css_animation .pswp__preloader__donut{-webkit-box-sizing:border-box;box-sizing:border-box;width:14px;height:14px;border:2px solid #FFF;border-radius:50%;border-left-color:transparent;border-bottom-color:transparent;position:absolute;top:0;left:0;background:none;margin:0}@media screen and (max-width:1024px){.pswp__preloader{position:relative;left:auto;top:auto;margin:0;float:right}}@-webkit-keyframes clockwise{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes clockwise{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes donut-rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}50%{-webkit-transform:rotate(-140deg);transform:rotate(-140deg)}100%{-webkit-transform:rotate(0);transform:rotate(0)}}@keyframes donut-rotate{0%{-webkit-transform:rotate(0);transform:rotate(0)}50%{-webkit-transform:rotate(-140deg);transform:rotate(-140deg)}100%{-webkit-transform:rotate(0);transform:rotate(0)}}.pswp__ui{-webkit-font-smoothing:auto;visibility:visible;opacity:1;z-index:1550}.pswp__top-bar{position:absolute;left:0;top:0;height:44px;width:100%}.pswp__caption,.pswp__top-bar,.pswp--has_mouse .pswp__button--arrow--left,.pswp--has_mouse .pswp__button--arrow--right{-webkit-backface-visibility:hidden;will-change:opacity;-webkit-transition:opacity 333ms cubic-bezier(0.4,0,0.22,1);transition:opacity 333ms cubic-bezier(0.4,0,0.22,1)}.pswp--has_mouse .pswp__button--arrow--left,.pswp--has_mouse .pswp__button--arrow--right{visibility:visible}.pswp__top-bar,.pswp__caption{background-color:rgba(0,0,0,0.5)}.pswp__ui--fit .pswp__top-bar,.pswp__ui--fit .pswp__caption{background-color:rgba(0,0,0,0.3)}.pswp__ui--idle .pswp__top-bar{opacity:0}.pswp__ui--idle .pswp__button--arrow--left,.pswp__ui--idle .pswp__button--arrow--right{opacity:0}.pswp__ui--hidden .pswp__top-bar,.pswp__ui--hidden .pswp__caption,.pswp__ui--hidden .pswp__button--arrow--left,.pswp__ui--hidden .pswp__button--arrow--right{opacity:.001}.pswp__ui--one-slide .pswp__button--arrow--left,.pswp__ui--one-slide .pswp__button--arrow--right,.pswp__ui--one-slide .pswp__counter{display:none}.pswp__element--disabled{display:none!important}.pswp--minimal--dark .pswp__top-bar{background:none}/*!PhotoSwipe main CSS by Dmitry Semenov | photoswipe.com | MIT license */ .pswp{display:none;position:absolute;width:100%;height:100%;left:0;top:0;overflow:hidden;-ms-touch-action:none;touch-action:none;z-index:1500;-webkit-text-size-adjust:100%;-webkit-backface-visibility:hidden;outline:none}.pswp *{-webkit-box-sizing:border-box;box-sizing:border-box}.pswp img{max-width:none}.pswp--animate_opacity{opacity:.001;will-change:opacity;-webkit-transition:opacity 333ms cubic-bezier(0.4,0,0.22,1);transition:opacity 333ms cubic-bezier(0.4,0,0.22,1)}.pswp--open{display:block}.pswp--zoom-allowed .pswp__img{cursor:-webkit-zoom-in;cursor:-moz-zoom-in;cursor:zoom-in}.pswp--zoomed-in .pswp__img{cursor:-webkit-grab;cursor:-moz-grab;cursor:grab}.pswp--dragging .pswp__img{cursor:-webkit-grabbing;cursor:-moz-grabbing;cursor:grabbing}.pswp__bg{position:absolute;left:0;top:0;width:100%;height:100%;background:#000;opacity:0;-webkit-backface-visibility:hidden;will-change:opacity}.pswp__scroll-wrap{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden}.pswp__container,.pswp__zoom-wrap{-ms-touch-action:none;touch-action:none;position:absolute;left:0;right:0;top:0;bottom:0}.pswp__container,.pswp__img{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.pswp__zoom-wrap{position:absolute;width:100%;-webkit-transform-origin:left top;-ms-transform-origin:left top;transform-origin:left top;-webkit-transition:-webkit-transform 333ms cubic-bezier(0.4,0,0.22,1);transition:transform 333ms cubic-bezier(0.4,0,0.22,1)}.pswp__bg{will-change:opacity;-webkit-transition:opacity 333ms cubic-bezier(0.4,0,0.22,1);transition:opacity 333ms cubic-bezier(0.4,0,0.22,1)}.pswp--animated-in .pswp__bg,.pswp--animated-in .pswp__zoom-wrap{-webkit-transition:none;transition:none}.pswp__container,.pswp__zoom-wrap{-webkit-backface-visibility:hidden}.pswp__item{position:absolute;left:0;right:0;top:0;bottom:0;overflow:hidden}.pswp__img{position:absolute;width:auto;height:auto;top:0;left:0}.pswp__img--placeholder{-webkit-backface-visibility:hidden}.pswp__img--placeholder--blank{background:#222}.pswp--ie .pswp__img{width:100%!important;height:auto!important;left:0;top:0}.pswp__error-msg{position:absolute;left:0;top:50%;width:100%;text-align:center;font-size:14px;line-height:16px;margin-top:-8px;color:#CCC}.pswp__error-msg a{color:#CCC;text-decoration:underline}
\ No newline at end of file
diff --git a/sigal/themes/photoswipe/templates/index.html b/sigal/themes/photoswipe/templates/index.html
index b78373b..d2bfc23 100644
--- a/sigal/themes/photoswipe/templates/index.html
+++ b/sigal/themes/photoswipe/templates/index.html
@@ -9,7 +9,9 @@
-
+
+
+