mirror of https://github.com/saimn/sigal.git
33 changed files with 10409 additions and 5597 deletions
@ -0,0 +1,29 @@
|
||||
{% macro img_description(media, with_big=True) -%} |
||||
{%- if with_big and media.big -%} |
||||
<a href='{{ media.big_url }}'>Full size</a> |
||||
{%- endif -%} |
||||
{%- if media.description -%} |
||||
<br>{{ media.description }} |
||||
{%- endif -%} |
||||
{%- if media.exif -%} |
||||
<div class='film-meta'> |
||||
{%- if media.exif.iso -%} |
||||
<abbr title='film speed'>{{ media.exif.iso }}</abbr> {%- endif -%} |
||||
{%- if media.exif.exposure -%} |
||||
<abbr title='exposure'>{{ media.exif.exposure }}</abbr> {%- endif -%} |
||||
{%- if media.exif.fstop -%} |
||||
<abbr title='aperture'>{{ media.exif.fstop }}</abbr> {%- endif -%} |
||||
{%- if media.exif.focal -%} |
||||
<abbr title='focal length'>{{ media.exif.focal }}</abbr> {%- endif -%} |
||||
</div> |
||||
{%- if media.exif.gps -%} |
||||
<a title='location' href='https://www.openstreetmap.org/?mlat={{ media.exif.gps.lat }}&mlon={{ media.exif.gps.lon}}&zoom=12&layers=M' target='_blank' class='map' >{{ 'N{:.6f}'.format(media.exif.gps.lat) if media.exif.gps.lat > 0 else 'S{:.6f}'.format(-media.exif.gps.lat) }}{{ 'E{:.6f}'.format(media.exif.gps.lon) if media.exif.gps.lon > 0 else 'W{:.6f}'.format(-media.exif.gps.lon) }}</a> |
||||
{%- endif -%} |
||||
{%- if media.exif.Make or media.exif.Model -%} |
||||
<abbr title='camera make and model'>{{ media.exif.Make }} {{ media.exif.Model }}</abbr> |
||||
{%- endif -%} |
||||
{%- if media.exif.datetime -%} |
||||
<abbr title='date'>{{ media.exif.datetime }}</abbr> |
||||
{%- endif -%} |
||||
{% endif %} |
||||
{%- endmacro %} |
||||
@ -1,214 +0,0 @@
|
||||
echo.init({ |
||||
offset: 100, |
||||
throttle: 250, |
||||
unload: false |
||||
}); |
||||
|
||||
var initPhotoSwipeFromDOM = function(gallerySelector) { |
||||
|
||||
// parse slide data (url, title, size ...) from DOM elements
|
||||
// (children of gallerySelector)
|
||||
var parseThumbnailElements = function(el) { |
||||
var thumbElements = el.childNodes, |
||||
numNodes = thumbElements.length, |
||||
items = [], |
||||
figureEl, |
||||
linkEl, |
||||
size, |
||||
item; |
||||
|
||||
for(var i = 0; i < numNodes; i++) { |
||||
|
||||
figureEl = thumbElements[i]; // <figure> element
|
||||
|
||||
// include only element nodes
|
||||
if(figureEl.nodeType !== 1) { |
||||
continue; |
||||
} |
||||
|
||||
linkEl = figureEl.children[0]; // <a> element
|
||||
|
||||
// create slide object
|
||||
if (linkEl.getAttribute('data-type') == 'video') { |
||||
item = { |
||||
html: linkEl.getAttribute('data-video') |
||||
}; |
||||
} else { |
||||
size = linkEl.getAttribute('data-size').split('x'); |
||||
item = { |
||||
src: linkEl.getAttribute('href'), |
||||
w: parseInt(size[0], 10), |
||||
h: parseInt(size[1], 10) |
||||
}; |
||||
} |
||||
|
||||
if(figureEl.children.length > 1) { |
||||
// <figcaption> content
|
||||
item.title = figureEl.children[1].innerHTML; |
||||
} |
||||
|
||||
if(linkEl.children.length > 0) { |
||||
// <img> thumbnail element, retrieving thumbnail url
|
||||
item.msrc = linkEl.children[0].getAttribute('data-echo'); |
||||
} |
||||
|
||||
item.el = figureEl; // save link to element for getThumbBoundsFn
|
||||
items.push(item); |
||||
} |
||||
|
||||
return items; |
||||
}; |
||||
|
||||
// find nearest parent element
|
||||
var closest = function closest(el, fn) { |
||||
return el && ( fn(el) ? el : closest(el.parentNode, fn) ); |
||||
}; |
||||
|
||||
// triggers when user clicks on thumbnail
|
||||
var onThumbnailsClick = function(e) { |
||||
e = e || window.event; |
||||
e.preventDefault ? e.preventDefault() : e.returnValue = false; |
||||
|
||||
var eTarget = e.target || e.srcElement; |
||||
|
||||
// find root element of slide
|
||||
var clickedListItem = closest(eTarget, function(el) { |
||||
return (el.tagName && el.tagName.toUpperCase() === 'FIGURE'); |
||||
}); |
||||
|
||||
if(!clickedListItem) { |
||||
return; |
||||
} |
||||
|
||||
// find index of clicked item by looping through all child nodes
|
||||
// alternatively, you may define index via data- attribute
|
||||
var clickedGallery = clickedListItem.parentNode, |
||||
childNodes = clickedListItem.parentNode.childNodes, |
||||
numChildNodes = childNodes.length, |
||||
nodeIndex = 0, |
||||
index; |
||||
|
||||
for (var i = 0; i < numChildNodes; i++) { |
||||
if(childNodes[i].nodeType !== 1) { |
||||
continue; |
||||
} |
||||
|
||||
if(childNodes[i] === clickedListItem) { |
||||
index = nodeIndex; |
||||
break; |
||||
} |
||||
nodeIndex++; |
||||
} |
||||
|
||||
|
||||
|
||||
if(index >= 0) { |
||||
// open PhotoSwipe if valid index found
|
||||
openPhotoSwipe( index, clickedGallery ); |
||||
} |
||||
return false; |
||||
}; |
||||
|
||||
// parse picture index and gallery index from URL (#&pid=1&gid=2)
|
||||
var photoswipeParseHash = function() { |
||||
var hash = window.location.hash.substring(1), |
||||
params = {}; |
||||
|
||||
if(hash.length < 5) { |
||||
return params; |
||||
} |
||||
|
||||
var vars = hash.split('&'); |
||||
for (var 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(params.gid) { |
||||
params.gid = parseInt(params.gid, 10); |
||||
} |
||||
|
||||
return params; |
||||
}; |
||||
|
||||
var openPhotoSwipe = function(index, galleryElement, disableAnimation, fromURL) { |
||||
var pswpElement = document.querySelectorAll('.pswp')[0], |
||||
gallery, |
||||
options, |
||||
items; |
||||
|
||||
items = parseThumbnailElements(galleryElement); |
||||
|
||||
// define options (if needed)
|
||||
options = { |
||||
|
||||
// define gallery index (for URL)
|
||||
galleryUID: galleryElement.getAttribute('data-pswp-uid'), |
||||
|
||||
getThumbBoundsFn: function(index) { |
||||
// See Options -> getThumbBoundsFn section of documentation for more info
|
||||
var thumbnail = items[index].el.getElementsByTagName('img')[0], // find thumbnail
|
||||
pageYScroll = window.pageYOffset || document.documentElement.scrollTop, |
||||
rect = thumbnail.getBoundingClientRect(); |
||||
|
||||
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width}; |
||||
} |
||||
|
||||
}; |
||||
|
||||
// PhotoSwipe opened from URL
|
||||
if(fromURL) { |
||||
if(options.galleryPIDs) { |
||||
// parse real index when custom PIDs are used
|
||||
// http://photoswipe.com/documentation/faq.html#custom-pid-in-url
|
||||
for(var j = 0; j < items.length; j++) { |
||||
if(items[j].pid == index) { |
||||
options.index = j; |
||||
break; |
||||
} |
||||
} |
||||
} else { |
||||
// in URL indexes start from 1
|
||||
options.index = parseInt(index, 10) - 1; |
||||
} |
||||
} else { |
||||
options.index = parseInt(index, 10); |
||||
} |
||||
|
||||
// exit if index not found
|
||||
if( isNaN(options.index) ) { |
||||
return; |
||||
} |
||||
|
||||
if(disableAnimation) { |
||||
options.showAnimationDuration = 0; |
||||
} |
||||
|
||||
// Pass data to PhotoSwipe and initialize it
|
||||
gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options); |
||||
gallery.init(); |
||||
}; |
||||
|
||||
// loop through all gallery elements and bind events
|
||||
var galleryElements = document.querySelectorAll( gallerySelector ); |
||||
|
||||
for(var i = 0, l = galleryElements.length; i < l; i++) { |
||||
galleryElements[i].setAttribute('data-pswp-uid', i+1); |
||||
galleryElements[i].onclick = onThumbnailsClick; |
||||
} |
||||
|
||||
// Parse URL and open gallery if it contains #&pid=3&gid=1
|
||||
var hashData = photoswipeParseHash(); |
||||
if(hashData.pid && hashData.gid) { |
||||
openPhotoSwipe( hashData.pid , galleryElements[ hashData.gid - 1 ], true, true ); |
||||
} |
||||
}; |
||||
|
||||
// execute above function
|
||||
initPhotoSwipeFromDOM('.gallery'); |
||||
@ -1,485 +0,0 @@
|
||||
/*! PhotoSwipe Default UI CSS by Dmitry Semenov | photoswipe.com | MIT license */ |
||||
/* |
||||
|
||||
Contents: |
||||
|
||||
1. Buttons |
||||
2. Share modal and links |
||||
3. Index indicator ("1 of X" counter) |
||||
4. Caption |
||||
5. Loading indicator |
||||
6. Additional styles (root element, top bar, idle state, hidden state, etc.) |
||||
|
||||
*/ |
||||
/* |
||||
|
||||
1. Buttons |
||||
|
||||
*/ |
||||
/* <button> css reset */ |
||||
.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: 0.75; |
||||
-webkit-transition: opacity 0.2s; |
||||
transition: opacity 0.2s; |
||||
-webkit-box-shadow: none; |
||||
box-shadow: none; } |
||||
.pswp__button:focus, .pswp__button:hover { |
||||
opacity: 1; } |
||||
.pswp__button:active { |
||||
outline: none; |
||||
opacity: 0.9; } |
||||
.pswp__button::-moz-focus-inner { |
||||
padding: 0; |
||||
border: 0; } |
||||
|
||||
/* pswp__ui--over-close class it added when mouse is over element that should close gallery */ |
||||
.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.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) { |
||||
/* Serve SVG sprite if browser supports SVG and resolution is more than 105dpi */ |
||||
.pswp--svg .pswp__button, |
||||
.pswp--svg .pswp__button--arrow--left:before, |
||||
.pswp--svg .pswp__button--arrow--right:before { |
||||
background-image: url(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--download { |
||||
background-position: -176px 0; } |
||||
|
||||
.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; } |
||||
|
||||
/* no arrows on touch screens */ |
||||
.pswp--touch:not(.pswp--preventswipe) .pswp__button--arrow--left, |
||||
.pswp--touch:not(.pswp--preventswipe) .pswp__button--arrow--right { |
||||
visibility: hidden; } |
||||
|
||||
/* |
||||
Arrow buttons hit area |
||||
(icon is added to :before pseudo-element) |
||||
*/ |
||||
.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; } |
||||
|
||||
/* |
||||
|
||||
2. Share modal/popup and links |
||||
|
||||
*/ |
||||
.pswp__counter, |
||||
.pswp__share-modal { |
||||
-webkit-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: 16777371; |
||||
opacity: 0; |
||||
-webkit-transition: opacity 0.25s ease-out; |
||||
transition: opacity 0.25s ease-out; |
||||
-webkit-backface-visibility: hidden; |
||||
will-change: opacity; } |
||||
|
||||
.pswp__share-modal--hidden { |
||||
display: none; } |
||||
|
||||
.pswp__share-tooltip { |
||||
z-index: 16777391; |
||||
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 0.25s; |
||||
transition: transform 0.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 { |
||||
/* round corners on the first/last list item */ |
||||
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); } |
||||
|
||||
/* increase size of share links on touch devices */ |
||||
.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 rgba(0, 0, 0, 0); |
||||
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; } |
||||
|
||||
/* |
||||
|
||||
3. Index indicator ("1 of X" counter) |
||||
|
||||
*/ |
||||
.pswp__counter { |
||||
position: absolute; |
||||
left: 0; |
||||
top: 0; |
||||
height: 44px; |
||||
font-size: 13px; |
||||
line-height: 44px; |
||||
color: #fff; |
||||
opacity: 0.75; |
||||
padding: 0 10px; } |
||||
|
||||
/* |
||||
|
||||
4. Caption |
||||
|
||||
*/ |
||||
.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: center; |
||||
max-width: 420px; |
||||
margin: 0 auto; |
||||
font-size: 13px; |
||||
padding: 10px; |
||||
line-height: 20px; |
||||
color: #ccc; } |
||||
|
||||
.pswp__caption--empty { |
||||
display: none; } |
||||
|
||||
/* Fake caption element, used to calculate height of next/prev image */ |
||||
.pswp__caption--fake { |
||||
visibility: hidden; } |
||||
|
||||
/* |
||||
|
||||
5. Loading indicator (preloader) |
||||
|
||||
You can play with it here - http://codepen.io/dimsemenov/pen/yyBWoR |
||||
|
||||
*/ |
||||
.pswp__preloader { |
||||
width: 44px; |
||||
height: 44px; |
||||
position: absolute; |
||||
top: 0; |
||||
left: 50%; |
||||
margin-left: -22px; |
||||
opacity: 0; |
||||
-webkit-transition: opacity 0.25s ease-out; |
||||
transition: opacity 0.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 { |
||||
/* We use .gif in browsers that don't support CSS animation */ |
||||
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: 0.75; |
||||
width: 14px; |
||||
height: 14px; |
||||
position: absolute; |
||||
left: 15px; |
||||
top: 15px; |
||||
margin: 0; } |
||||
|
||||
.pswp--css_animation .pswp__preloader__cut { |
||||
/* |
||||
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; |
||||
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); } } |
||||
|
||||
/* |
||||
|
||||
6. Additional styles |
||||
|
||||
*/ |
||||
/* root element of UI */ |
||||
.pswp__ui { |
||||
-webkit-font-smoothing: auto; |
||||
visibility: visible; |
||||
opacity: 1; |
||||
z-index: 16777321; } |
||||
|
||||
/* top black bar with buttons and "1 of X" indicator */ |
||||
.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 class is added only when two subsequent mousemove events occur */ |
||||
.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 class is added when main image "fits" between top bar and bottom bar (caption) */ |
||||
.pswp__ui--fit .pswp__top-bar, |
||||
.pswp__ui--fit .pswp__caption { |
||||
background-color: rgba(0, 0, 0, 0.3); } |
||||
|
||||
/* pswp__ui--idle class is added when mouse isn't moving for several seconds (JS option timeToIdle) */ |
||||
.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 class is added when controls are hidden |
||||
e.g. when user taps to toggle visibility of controls |
||||
*/ |
||||
.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 { |
||||
/* Force paint & create composition layer for controls. */ |
||||
opacity: 0.001; |
||||
visibility: hidden; } |
||||
|
||||
/* pswp__ui--one-slide class is added when there is just one item in gallery */ |
||||
.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; } |
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 794 B |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 866 B |
|
Before Width: | Height: | Size: 42 B |
@ -1,135 +0,0 @@
|
||||
/*! echo-js v1.7.3 | (c) 2016 @toddmotto | https://github.com/toddmotto/echo */ |
||||
(function (root, factory) { |
||||
if (typeof define === 'function' && define.amd) { |
||||
define(function() { |
||||
return factory(root); |
||||
}); |
||||
} else if (typeof exports === 'object') { |
||||
module.exports = factory; |
||||
} else { |
||||
root.echo = factory(root); |
||||
} |
||||
})(this, function (root) { |
||||
|
||||
'use strict'; |
||||
|
||||
var echo = {}; |
||||
|
||||
var callback = function () {}; |
||||
|
||||
var offset, poll, delay, useDebounce, unload; |
||||
|
||||
var isHidden = function (element) { |
||||
return (element.offsetParent === null); |
||||
}; |
||||
|
||||
var inView = function (element, view) { |
||||
if (isHidden(element)) { |
||||
return false; |
||||
} |
||||
|
||||
var box = element.getBoundingClientRect(); |
||||
return (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b); |
||||
}; |
||||
|
||||
var debounceOrThrottle = function () { |
||||
if(!useDebounce && !!poll) { |
||||
return; |
||||
} |
||||
clearTimeout(poll); |
||||
poll = setTimeout(function(){ |
||||
echo.render(); |
||||
poll = null; |
||||
}, delay); |
||||
}; |
||||
|
||||
echo.init = function (opts) { |
||||
opts = opts || {}; |
||||
var offsetAll = opts.offset || 0; |
||||
var offsetVertical = opts.offsetVertical || offsetAll; |
||||
var offsetHorizontal = opts.offsetHorizontal || offsetAll; |
||||
var optionToInt = function (opt, fallback) { |
||||
return parseInt(opt || fallback, 10); |
||||
}; |
||||
offset = { |
||||
t: optionToInt(opts.offsetTop, offsetVertical), |
||||
b: optionToInt(opts.offsetBottom, offsetVertical), |
||||
l: optionToInt(opts.offsetLeft, offsetHorizontal), |
||||
r: optionToInt(opts.offsetRight, offsetHorizontal) |
||||
}; |
||||
delay = optionToInt(opts.throttle, 250); |
||||
useDebounce = opts.debounce !== false; |
||||
unload = !!opts.unload; |
||||
callback = opts.callback || callback; |
||||
echo.render(); |
||||
if (document.addEventListener) { |
||||
root.addEventListener('scroll', debounceOrThrottle, false); |
||||
root.addEventListener('load', debounceOrThrottle, false); |
||||
} else { |
||||
root.attachEvent('onscroll', debounceOrThrottle); |
||||
root.attachEvent('onload', debounceOrThrottle); |
||||
} |
||||
}; |
||||
|
||||
echo.render = function () { |
||||
var nodes = document.querySelectorAll('img[data-echo], [data-echo-background]'); |
||||
var length = nodes.length; |
||||
var src, elem; |
||||
var view = { |
||||
l: 0 - offset.l, |
||||
t: 0 - offset.t, |
||||
b: (root.innerHeight || document.documentElement.clientHeight) + offset.b, |
||||
r: (root.innerWidth || document.documentElement.clientWidth) + offset.r |
||||
}; |
||||
for (var i = 0; i < length; i++) { |
||||
elem = nodes[i]; |
||||
if (inView(elem, view)) { |
||||
|
||||
if (unload) { |
||||
elem.setAttribute('data-echo-placeholder', elem.src); |
||||
} |
||||
|
||||
if (elem.getAttribute('data-echo-background') !== null) { |
||||
elem.style.backgroundImage = "url(" + elem.getAttribute('data-echo-background') + ")"; |
||||
} |
||||
else { |
||||
elem.src = elem.getAttribute('data-echo'); |
||||
} |
||||
|
||||
if (!unload) { |
||||
elem.removeAttribute('data-echo'); |
||||
elem.removeAttribute('data-echo-background'); |
||||
} |
||||
|
||||
callback(elem, 'load'); |
||||
} |
||||
else if (unload && !!(src = elem.getAttribute('data-echo-placeholder'))) { |
||||
|
||||
if (elem.getAttribute('data-echo-background') !== null) { |
||||
elem.style.backgroundImage = "url(" + src + ")"; |
||||
} |
||||
else { |
||||
elem.src = src; |
||||
} |
||||
|
||||
elem.removeAttribute('data-echo-placeholder'); |
||||
callback(elem, 'unload'); |
||||
} |
||||
} |
||||
if (!length) { |
||||
echo.detach(); |
||||
} |
||||
}; |
||||
|
||||
echo.detach = function () { |
||||
if (document.removeEventListener) { |
||||
root.removeEventListener('scroll', debounceOrThrottle); |
||||
} else { |
||||
root.detachEvent('onscroll', debounceOrThrottle); |
||||
} |
||||
clearTimeout(poll); |
||||
}; |
||||
|
||||
return echo; |
||||
|
||||
}); |
||||
@ -1,2 +0,0 @@
|
||||
/*! echo-js v1.7.3 | (c) 2016 @toddmotto | https://github.com/toddmotto/echo */ |
||||
!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t)}):"object"==typeof exports?module.exports=e:t.echo=e(t)}(this,function(t){"use strict";var e,n,o,r,c,a={},u=function(){},d=function(t){return null===t.offsetParent},i=function(t,e){if(d(t))return!1;var n=t.getBoundingClientRect();return n.right>=e.l&&n.bottom>=e.t&&n.left<=e.r&&n.top<=e.b},l=function(){(r||!n)&&(clearTimeout(n),n=setTimeout(function(){a.render(),n=null},o))};return a.init=function(n){n=n||{};var d=n.offset||0,i=n.offsetVertical||d,f=n.offsetHorizontal||d,s=function(t,e){return parseInt(t||e,10)};e={t:s(n.offsetTop,i),b:s(n.offsetBottom,i),l:s(n.offsetLeft,f),r:s(n.offsetRight,f)},o=s(n.throttle,250),r=n.debounce!==!1,c=!!n.unload,u=n.callback||u,a.render(),document.addEventListener?(t.addEventListener("scroll",l,!1),t.addEventListener("load",l,!1)):(t.attachEvent("onscroll",l),t.attachEvent("onload",l))},a.render=function(){for(var n,o,r=document.querySelectorAll("img[data-echo], [data-echo-background]"),d=r.length,l={l:0-e.l,t:0-e.t,b:(t.innerHeight||document.documentElement.clientHeight)+e.b,r:(t.innerWidth||document.documentElement.clientWidth)+e.r},f=0;d>f;f++)o=r[f],i(o,l)?(c&&o.setAttribute("data-echo-placeholder",o.src),null!==o.getAttribute("data-echo-background")?o.style.backgroundImage="url("+o.getAttribute("data-echo-background")+")":o.src=o.getAttribute("data-echo"),c||(o.removeAttribute("data-echo"),o.removeAttribute("data-echo-background")),u(o,"load")):c&&(n=o.getAttribute("data-echo-placeholder"))&&(null!==o.getAttribute("data-echo-background")?o.style.backgroundImage="url("+n+")":o.src=n,o.removeAttribute("data-echo-placeholder"),u(o,"unload"));d||a.detach()},a.detach=function(){document.removeEventListener?t.removeEventListener("scroll",l):t.detachEvent("onscroll",l),clearTimeout(n)},a}); |
||||
@ -0,0 +1,414 @@
|
||||
/** |
||||
* PhotoSwipe Dynamic Caption plugin v1.2.7 |
||||
* https://github.com/dimsemenov/photoswipe-dynamic-caption-plugin
|
||||
*
|
||||
* By https://dimsemenov.com
|
||||
*/ |
||||
|
||||
const defaultOptions = { |
||||
captionContent: '.pswp-caption-content', |
||||
type: 'auto', |
||||
horizontalEdgeThreshold: 20, |
||||
mobileCaptionOverlapRatio: 0.3, |
||||
mobileLayoutBreakpoint: 600, |
||||
verticallyCenterImage: false |
||||
}; |
||||
|
||||
class PhotoSwipeDynamicCaption { |
||||
constructor(lightbox, options) { |
||||
this.options = { |
||||
...defaultOptions, |
||||
...options |
||||
}; |
||||
|
||||
this.lightbox = lightbox; |
||||
|
||||
this.lightbox.on('init', () => { |
||||
this.pswp = this.lightbox.pswp; |
||||
this.initCaption(); |
||||
}); |
||||
} |
||||
|
||||
initCaption() { |
||||
const { pswp } = this; |
||||
|
||||
pswp.on('change', () => { |
||||
// make sure caption is displayed after slides are switched
|
||||
this.showCaption(this.pswp.currSlide); |
||||
}); |
||||
|
||||
pswp.on('calcSlideSize', (e) => this.onCalcSlideSize(e)); |
||||
|
||||
pswp.on('slideDestroy', (e) => { |
||||
if (e.slide.dynamicCaption) { |
||||
if (e.slide.dynamicCaption.element) { |
||||
e.slide.dynamicCaption.element.remove(); |
||||
} |
||||
delete e.slide.dynamicCaption; |
||||
} |
||||
}); |
||||
|
||||
// hide caption if zoomed
|
||||
pswp.on('zoomPanUpdate', ({ slide }) => { |
||||
if (pswp.opener.isOpen && slide.dynamicCaption) { |
||||
if (slide.currZoomLevel > slide.zoomLevels.initial) { |
||||
this.hideCaption(slide); |
||||
} else { |
||||
this.showCaption(slide); |
||||
} |
||||
|
||||
// move caption on vertical drag
|
||||
if (slide.dynamicCaption.element) { |
||||
let captionYOffset = 0; |
||||
if (slide.currZoomLevel <= slide.zoomLevels.initial) { |
||||
const shiftedAmount = slide.pan.y - slide.bounds.center.y; |
||||
if (Math.abs(shiftedAmount) > 1) { |
||||
captionYOffset = shiftedAmount; |
||||
} |
||||
} |
||||
|
||||
this.setCaptionYOffset(slide.dynamicCaption.element, captionYOffset); |
||||
} |
||||
|
||||
this.adjustPanArea(slide, slide.currZoomLevel); |
||||
} |
||||
}); |
||||
|
||||
pswp.on('beforeZoomTo', (e) => { |
||||
this.adjustPanArea(pswp.currSlide, e.destZoomLevel); |
||||
}); |
||||
|
||||
// Stop default action of tap when tapping on the caption
|
||||
pswp.on('tapAction', (e) => { |
||||
if (e.originalEvent.target.closest('.pswp__dynamic-caption')) { |
||||
e.preventDefault(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
adjustPanArea(slide, zoomLevel) { |
||||
if (slide.dynamicCaption && slide.dynamicCaption.adjustedPanAreaSize) { |
||||
if (zoomLevel > slide.zoomLevels.initial) { |
||||
slide.panAreaSize.x = slide.dynamicCaption.originalPanAreaSize.x; |
||||
slide.panAreaSize.y = slide.dynamicCaption.originalPanAreaSize.y; |
||||
} else { |
||||
// Restore panAreaSize after we zoom back to initial position
|
||||
slide.panAreaSize.x = slide.dynamicCaption.adjustedPanAreaSize.x; |
||||
slide.panAreaSize.y = slide.dynamicCaption.adjustedPanAreaSize.y; |
||||
} |
||||
} |
||||
} |
||||
|
||||
useMobileLayout() { |
||||
const { mobileLayoutBreakpoint } = this.options; |
||||
|
||||
if (typeof mobileLayoutBreakpoint === 'function') { |
||||
return mobileLayoutBreakpoint.call(this); |
||||
} else if (typeof mobileLayoutBreakpoint === 'number') { |
||||
if (window.innerWidth < mobileLayoutBreakpoint) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
hideCaption(slide) { |
||||
if (slide.dynamicCaption && !slide.dynamicCaption.hidden) { |
||||
const captionElement = slide.dynamicCaption.element; |
||||
|
||||
if (!captionElement) { |
||||
return; |
||||
} |
||||
|
||||
slide.dynamicCaption.hidden = true; |
||||
captionElement.classList.add('pswp__dynamic-caption--faded'); |
||||
|
||||
// Disable caption visibility with the delay, so it's not interactable
|
||||
if (slide.captionFadeTimeout) { |
||||
clearTimeout(slide.captionFadeTimeout); |
||||
} |
||||
slide.captionFadeTimeout = setTimeout(() => { |
||||
captionElement.style.visibility = 'hidden'; |
||||
delete slide.captionFadeTimeout; |
||||
}, 400); |
||||
} |
||||
} |
||||
|
||||
setCaptionYOffset(el, y) { |
||||
el.style.transform = `translateY(${y}px)`; |
||||
} |
||||
|
||||
showCaption(slide) { |
||||
if (slide.dynamicCaption && slide.dynamicCaption.hidden) { |
||||
const captionElement = slide.dynamicCaption.element; |
||||
|
||||
if (!captionElement) { |
||||
return; |
||||
} |
||||
|
||||
slide.dynamicCaption.hidden = false; |
||||
captionElement.style.visibility = 'visible'; |
||||
|
||||
clearTimeout(slide.captionFadeTimeout); |
||||
slide.captionFadeTimeout = setTimeout(() => { |
||||
captionElement.classList.remove('pswp__dynamic-caption--faded'); |
||||
delete slide.captionFadeTimeout;; |
||||
}, 50); |
||||
} |
||||
} |
||||
|
||||
setCaptionPosition(captionEl, x, y) { |
||||
const isOnHorizontalEdge = (x <= this.options.horizontalEdgeThreshold); |
||||
captionEl.classList[ |
||||
isOnHorizontalEdge ? 'add' : 'remove' |
||||
]('pswp__dynamic-caption--on-hor-edge'); |
||||
|
||||
captionEl.style.left = x + 'px'; |
||||
captionEl.style.top = y + 'px'; |
||||
} |
||||
|
||||
setCaptionWidth(captionEl, width) { |
||||
if (!width) { |
||||
captionEl.style.removeProperty('width'); |
||||
} else { |
||||
captionEl.style.width = width + 'px'; |
||||
} |
||||
} |
||||
|
||||
setCaptionType(captionEl, type) { |
||||
const prevType = captionEl.dataset.pswpCaptionType; |
||||
if (type !== prevType) { |
||||
captionEl.classList.add('pswp__dynamic-caption--' + type); |
||||
captionEl.classList.remove('pswp__dynamic-caption--' + prevType); |
||||
captionEl.dataset.pswpCaptionType = type; |
||||
} |
||||
} |
||||
|
||||
updateCaptionPosition(slide) { |
||||
if (!slide.dynamicCaption || !slide.dynamicCaption.type || !slide.dynamicCaption.element) { |
||||
return; |
||||
} |
||||
|
||||
if (slide.dynamicCaption.type === 'mobile') { |
||||
this.setCaptionType( |
||||
slide.dynamicCaption.element,
|
||||
slide.dynamicCaption.type |
||||
); |
||||
|
||||
slide.dynamicCaption.element.style.removeProperty('left'); |
||||
slide.dynamicCaption.element.style.removeProperty('top'); |
||||
this.setCaptionWidth(slide.dynamicCaption.element, false); |
||||
return; |
||||
} |
||||
|
||||
const zoomLevel = slide.zoomLevels.initial; |
||||
const imageWidth = Math.ceil(slide.width * zoomLevel); |
||||
const imageHeight = Math.ceil(slide.height * zoomLevel); |
||||
|
||||
this.setCaptionType(slide.dynamicCaption.element, slide.dynamicCaption.type); |
||||
if (slide.dynamicCaption.type === 'aside') { |
||||
this.setCaptionPosition( |
||||
slide.dynamicCaption.element, |
||||
slide.bounds.center.x + imageWidth, |
||||
slide.bounds.center.y |
||||
); |
||||
this.setCaptionWidth(slide.dynamicCaption.element, false); |
||||
} else if (slide.dynamicCaption.type === 'below') { |
||||
this.setCaptionPosition( |
||||
slide.dynamicCaption.element, |
||||
slide.bounds.center.x, |
||||
slide.bounds.center.y + imageHeight |
||||
); |
||||
this.setCaptionWidth(slide.dynamicCaption.element, imageWidth); |
||||
} |
||||
} |
||||
|
||||
onCalcSlideSize(e) { |
||||
const { slide } = e; |
||||
let captionSize; |
||||
let useMobileVersion; |
||||
|
||||
if (!slide.dynamicCaption) { |
||||
slide.dynamicCaption = { |
||||
element: undefined, |
||||
type: false, |
||||
hidden: false |
||||
}; |
||||
|
||||
const captionHTML = this.getCaptionHTML(slide); |
||||
|
||||
if (!captionHTML) { |
||||
return; |
||||
} |
||||
|
||||
slide.dynamicCaption.element = document.createElement('div'); |
||||
slide.dynamicCaption.element.className = 'pswp__dynamic-caption pswp__hide-on-close'; |
||||
slide.dynamicCaption.element.innerHTML = captionHTML; |
||||
|
||||
this.pswp.dispatch('dynamicCaptionUpdateHTML', {
|
||||
captionElement: slide.dynamicCaption.element, |
||||
slide |
||||
}); |
||||
|
||||
slide.holderElement.appendChild(slide.dynamicCaption.element); |
||||
} |
||||
|
||||
if (!slide.dynamicCaption.element) { |
||||
return; |
||||
} |
||||
|
||||
this.storeOriginalPanAreaSize(slide); |
||||
|
||||
slide.bounds.update(slide.zoomLevels.initial); |
||||
|
||||
if (this.useMobileLayout()) { |
||||
slide.dynamicCaption.type = 'mobile'; |
||||
useMobileVersion = true; |
||||
} else { |
||||
if (this.options.type === 'auto') { |
||||
if (slide.bounds.center.x > slide.bounds.center.y) { |
||||
slide.dynamicCaption.type = 'aside'; |
||||
} else { |
||||
slide.dynamicCaption.type = 'below'; |
||||
} |
||||
} else { |
||||
slide.dynamicCaption.type = this.options.type; |
||||
} |
||||
}
|
||||
|
||||
const imageWidth = Math.ceil(slide.width * slide.zoomLevels.initial); |
||||
const imageHeight = Math.ceil(slide.height * slide.zoomLevels.initial); |
||||
|
||||
this.setCaptionType( |
||||
slide.dynamicCaption.element,
|
||||
slide.dynamicCaption.type |
||||
); |
||||
|
||||
if (slide.dynamicCaption.type === 'aside') { |
||||
this.setCaptionWidth(slide.dynamicCaption.element, false); |
||||
captionSize = this.measureCaptionSize(slide.dynamicCaption.element, e.slide); |
||||
|
||||
const captionWidth = captionSize.x;
|
||||
|
||||
const horizontalEnding = imageWidth + slide.bounds.center.x; |
||||
const horizontalLeftover = (slide.panAreaSize.x - horizontalEnding); |
||||
|
||||
if (horizontalLeftover <= captionWidth) { |
||||
slide.panAreaSize.x -= captionWidth; |
||||
this.recalculateZoomLevelAndBounds(slide); |
||||
} else { |
||||
// do nothing, caption will fit aside without any adjustments
|
||||
} |
||||
} else if (slide.dynamicCaption.type === 'below' || useMobileVersion) { |
||||
this.setCaptionWidth( |
||||
slide.dynamicCaption.element,
|
||||
useMobileVersion ? this.pswp.viewportSize.x : imageWidth |
||||
); |
||||
|
||||
captionSize = this.measureCaptionSize(slide.dynamicCaption.element, e.slide); |
||||
const captionHeight = captionSize.y; |
||||
|
||||
if (this.options.verticallyCenterImage) { |
||||
slide.panAreaSize.y -= captionHeight; |
||||
this.recalculateZoomLevelAndBounds(slide); |
||||
} else { |
||||
// Lift up the image only by caption height
|
||||
|
||||
// vertical ending of the image
|
||||
const verticalEnding = imageHeight + slide.bounds.center.y; |
||||
|
||||
// height between bottom of the screen and ending of the image
|
||||
// (before any adjustments applied)
|
||||
const verticalLeftover = slide.panAreaSize.y - verticalEnding; |
||||
const initialPanAreaHeight = slide.panAreaSize.y; |
||||
|
||||
if (verticalLeftover <= captionHeight) { |
||||
// lift up the image to give more space for caption
|
||||
slide.panAreaSize.y -= Math.min((captionHeight - verticalLeftover) * 2, captionHeight); |
||||
|
||||
// we reduce viewport size, thus we need to update zoom level and pan bounds
|
||||
this.recalculateZoomLevelAndBounds(slide); |
||||
|
||||
const maxPositionX = slide.panAreaSize.x * this.options.mobileCaptionOverlapRatio / 2; |
||||
|
||||
// Do not reduce viewport height if too few space available
|
||||
if (useMobileVersion
|
||||
&& slide.bounds.center.x > maxPositionX) { |
||||
// Restore the default position
|
||||
slide.panAreaSize.y = initialPanAreaHeight; |
||||
this.recalculateZoomLevelAndBounds(slide); |
||||
} |
||||
} |
||||
} |
||||
} else { |
||||
// mobile
|
||||
} |
||||
|
||||
this.storeAdjustedPanAreaSize(slide); |
||||
this.updateCaptionPosition(slide); |
||||
} |
||||
|
||||
measureCaptionSize(captionEl, slide) { |
||||
const rect = captionEl.getBoundingClientRect(); |
||||
const event = this.pswp.dispatch('dynamicCaptionMeasureSize', { |
||||
captionEl, |
||||
slide, |
||||
captionSize: { |
||||
x: rect.width, |
||||
y: rect.height |
||||
} |
||||
}); |
||||
return event.captionSize; |
||||
} |
||||
|
||||
recalculateZoomLevelAndBounds(slide) { |
||||
slide.zoomLevels.update(slide.width, slide.height, slide.panAreaSize); |
||||
slide.bounds.update(slide.zoomLevels.initial); |
||||
} |
||||
|
||||
storeAdjustedPanAreaSize(slide) { |
||||
if (slide.dynamicCaption) { |
||||
if (!slide.dynamicCaption.adjustedPanAreaSize) { |
||||
slide.dynamicCaption.adjustedPanAreaSize = {}; |
||||
} |
||||
slide.dynamicCaption.adjustedPanAreaSize.x = slide.panAreaSize.x; |
||||
slide.dynamicCaption.adjustedPanAreaSize.y = slide.panAreaSize.y; |
||||
} |
||||
} |
||||
|
||||
storeOriginalPanAreaSize(slide) { |
||||
if (slide.dynamicCaption) { |
||||
if (!slide.dynamicCaption.originalPanAreaSize) { |
||||
slide.dynamicCaption.originalPanAreaSize = {}; |
||||
} |
||||
slide.dynamicCaption.originalPanAreaSize.x = slide.panAreaSize.x; |
||||
slide.dynamicCaption.originalPanAreaSize.y = slide.panAreaSize.y; |
||||
} |
||||
} |
||||
|
||||
getCaptionHTML(slide) { |
||||
if (typeof this.options.captionContent === 'function') { |
||||
return this.options.captionContent.call(this, slide); |
||||
} |
||||
|
||||
const currSlideElement = slide.data.element; |
||||
let captionHTML = ''; |
||||
if (currSlideElement) { |
||||
const hiddenCaption = currSlideElement.querySelector(this.options.captionContent); |
||||
if (hiddenCaption) { |
||||
// get caption from element with class pswp-caption-content
|
||||
captionHTML = hiddenCaption.innerHTML; |
||||
} else { |
||||
const img = currSlideElement.querySelector('img'); |
||||
if (img) { |
||||
// get caption from alt attribute
|
||||
captionHTML = img.getAttribute('alt'); |
||||
} |
||||
} |
||||
} |
||||
return captionHTML; |
||||
} |
||||
} |
||||
|
||||
export default PhotoSwipeDynamicCaption; |
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,129 @@
|
||||
/** |
||||
* PhotoSwipe fullscreen plugin v1.0.5 |
||||
* |
||||
* Inspired by https://github.com/dimsemenov/PhotoSwipe/issues/1759
|
||||
* |
||||
* By https://arnowelzel.de
|
||||
*/ |
||||
|
||||
const defaultOptions = { |
||||
fullscreenTitle: 'Toggle fullscreen' |
||||
}; |
||||
|
||||
class PhotoSwipeFullscreen { |
||||
constructor(lightbox, options) { |
||||
this.options = { |
||||
...defaultOptions, |
||||
...options |
||||
}; |
||||
this.lightbox = lightbox; |
||||
this.lightbox.on('init', () => { |
||||
this.initPlugin(this.lightbox.pswp); |
||||
}); |
||||
} |
||||
|
||||
initPlugin(pswp) { |
||||
this.fullscreenAPI = this.getFullscreenAPI(); |
||||
const fullscreenSVG = '<svg aria-hidden="true" class="pswp__icn" viewBox="0 0 32 32" width="32" height="32">' + |
||||
'<use class="pswp__icn-shadow" xlink:href="#pswp__icn-fullscreen-exit"/>' + |
||||
'<use class="pswp__icn-shadow" xlink:href="#pswp__icn-fullscreen-request"/>' + |
||||
'<path id="pswp__icn-fullscreen-request" transform="translate(4,4)" d="M20 3h2v6h-2V5h-4V3h4zM4 3h4v2H4v4H2V3h2zm16 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z" /></g>' + |
||||
'<path id="pswp__icn-fullscreen-exit" style="display:none" transform="translate(4,4)" d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"/>' + |
||||
'</svg>'; |
||||
|
||||
if (this.fullscreenAPI) { |
||||
pswp.on('uiRegister', () => { |
||||
pswp.ui.registerElement({ |
||||
name: 'fullscreen-button', |
||||
title: this.options.fullscreenTitle, |
||||
order: 9, |
||||
isButton: true, |
||||
html: fullscreenSVG, |
||||
onClick: (event, el) => { |
||||
this.toggleFullscreen(); |
||||
} |
||||
}); |
||||
|
||||
pswp.events.add(document, 'keydown', (e) => { |
||||
if (e.keyCode == 70) { // 'f'
|
||||
this.toggleFullscreen(); |
||||
e.preventDefault(); |
||||
} |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
this.lightbox.on('close', () => { |
||||
if (this.fullscreenAPI && this.fullscreenAPI.isFullscreen()) { |
||||
this.fullscreenAPI.exit(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
toggleFullscreen() { |
||||
if (this.fullscreenAPI) { |
||||
if (this.fullscreenAPI.isFullscreen()) { |
||||
// Exit full-screen mode
|
||||
this.fullscreenAPI.exit(); |
||||
// Toggle "Exit" and "Enter" full-screen SVG icon display
|
||||
setTimeout(function() { |
||||
document.getElementById('pswp__icn-fullscreen-exit').style.display = 'none'; |
||||
document.getElementById('pswp__icn-fullscreen-request').style.display = 'inline'; |
||||
}, 300); |
||||
} else { |
||||
// Enter full-screen mode
|
||||
this.fullscreenAPI.request(document.querySelector(`.pswp`)); |
||||
// Toggle "Exit" and "Enter" full-screen SVG icon display
|
||||
setTimeout(function() { |
||||
document.getElementById('pswp__icn-fullscreen-exit').style.display = 'inline'; |
||||
document.getElementById('pswp__icn-fullscreen-request').style.display = 'none'; |
||||
}, 300); |
||||
} |
||||
} |
||||
} |
||||
|
||||
getFullscreenAPI() { |
||||
let api; |
||||
let enterFS; |
||||
let exitFS; |
||||
let elementFS; |
||||
let changeEvent; |
||||
let errorEvent; |
||||
|
||||
if (document.fullscreenEnabled) { |
||||
enterFS = 'requestFullscreen'; |
||||
exitFS = 'exitFullscreen'; |
||||
elementFS = 'fullscreenElement'; |
||||
changeEvent = 'fullscreenchange'; |
||||
errorEvent = 'fullscreenerror'; |
||||
} else if (document.webkitFullscreenEnabled) { |
||||
enterFS = 'webkitRequestFullscreen'; |
||||
exitFS = 'webkitExitFullscreen'; |
||||
elementFS = 'webkitFullscreenElement'; |
||||
changeEvent = 'webkitfullscreenchange'; |
||||
errorEvent = 'webkitfullscreenerror'; |
||||
} |
||||
if (enterFS) { |
||||
api = { |
||||
request: function (el) { |
||||
if (enterFS === 'webkitRequestFullscreen') { |
||||
el[enterFS](Element.ALLOW_KEYBOARD_INPUT); |
||||
} else { |
||||
el[enterFS](); |
||||
} |
||||
}, |
||||
exit: function () { |
||||
return document[exitFS](); |
||||
}, |
||||
isFullscreen: function () { |
||||
return document[elementFS]; |
||||
}, |
||||
change: changeEvent, |
||||
error: errorEvent |
||||
}; |
||||
} |
||||
return api; |
||||
} |
||||
} |
||||
|
||||
export default PhotoSwipeFullscreen; |
||||
@ -0,0 +1,8 @@
|
||||
const defaultOptions={fullscreenTitle:'Toggle fullscreen'};class PhotoSwipeFullscreen{constructor(lightbox,options){this.options={...defaultOptions,...options};this.lightbox=lightbox;this.lightbox.on('init',()=>{this.initPlugin(this.lightbox.pswp)})} |
||||
initPlugin(pswp){this.fullscreenAPI=this.getFullscreenAPI();const fullscreenSVG='<svg aria-hidden="true" class="pswp__icn" viewBox="0 0 32 32" width="32" height="32">'+'<use class="pswp__icn-shadow" xlink:href="#pswp__icn-fullscreen-exit"/>'+'<use class="pswp__icn-shadow" xlink:href="#pswp__icn-fullscreen-request"/>'+'<path id="pswp__icn-fullscreen-request" transform="translate(4,4)" d="M20 3h2v6h-2V5h-4V3h4zM4 3h4v2H4v4H2V3h2zm16 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z" /></g>'+'<path id="pswp__icn-fullscreen-exit" style="display:none" transform="translate(4,4)" d="M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z"/>'+'</svg>';if(this.fullscreenAPI){pswp.on('uiRegister',()=>{pswp.ui.registerElement({name:'fullscreen-button',title:this.options.fullscreenTitle,order:9,isButton:!0,html:fullscreenSVG,onClick:(event,el)=>{this.toggleFullscreen()}});pswp.events.add(document,'keydown',(e)=>{if(e.keyCode==70){this.toggleFullscreen();e.preventDefault()}})})} |
||||
this.lightbox.on('close',()=>{if(this.fullscreenAPI&&this.fullscreenAPI.isFullscreen()){this.fullscreenAPI.exit()}})} |
||||
toggleFullscreen(){if(this.fullscreenAPI){if(this.fullscreenAPI.isFullscreen()){this.fullscreenAPI.exit();setTimeout(function(){document.getElementById('pswp__icn-fullscreen-exit').style.display='none';document.getElementById('pswp__icn-fullscreen-request').style.display='inline'},300)}else{this.fullscreenAPI.request(document.querySelector(`.pswp`));setTimeout(function(){document.getElementById('pswp__icn-fullscreen-exit').style.display='inline';document.getElementById('pswp__icn-fullscreen-request').style.display='none'},300)}}} |
||||
getFullscreenAPI(){let api;let enterFS;let exitFS;let elementFS;let changeEvent;let errorEvent;if(document.fullscreenEnabled){enterFS='requestFullscreen';exitFS='exitFullscreen';elementFS='fullscreenElement';changeEvent='fullscreenchange';errorEvent='fullscreenerror'}else if(document.webkitFullscreenEnabled){enterFS='webkitRequestFullscreen';exitFS='webkitExitFullscreen';elementFS='webkitFullscreenElement';changeEvent='webkitfullscreenchange';errorEvent='webkitfullscreenerror'} |
||||
if(enterFS){api={request:function(el){if(enterFS==='webkitRequestFullscreen'){el[enterFS](Element.ALLOW_KEYBOARD_INPUT)}else{el[enterFS]()}},exit:function(){return document[exitFS]()},isFullscreen:function(){return document[elementFS]},change:changeEvent,error:errorEvent}} |
||||
return api}} |
||||
export default PhotoSwipeFullscreen |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,871 +0,0 @@
|
||||
/*! |
||||
* PhotoSwipe Default UI - 4.4.0 - 2020-12-06 |
||||
* http://photoswipe.com
|
||||
* Copyright (c) 2020 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, |
||||
_stopAllAnimations, |
||||
_controls, |
||||
_captionContainer, |
||||
_fakeCaptionContainer, |
||||
_indexIndicator, |
||||
_prevButton, |
||||
_nextButton, |
||||
_shareButton, |
||||
_shareModal, |
||||
_shareModalHidden = true, |
||||
_downloadButton, |
||||
_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) { |
||||
framework.resetEl(captionEl.firstChild); |
||||
return false; |
||||
} |
||||
captionEl.children[0].innerHTML = item.title; |
||||
return true; |
||||
}, |
||||
|
||||
closeEl: true, |
||||
captionEl: true, |
||||
fullscreenEl: true, |
||||
zoomEl: true, |
||||
shareEl: true, |
||||
downloadEl: true, |
||||
counterEl: true, |
||||
arrowEl: true, |
||||
preloaderEl: true, |
||||
closeOnOutsideClick: true, |
||||
|
||||
tapToClose: false, |
||||
tapToToggleControls: true, |
||||
|
||||
clickToCloseNonZoomable: true, |
||||
clickToShowNextNonZoomable: false, |
||||
|
||||
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; |
||||
} |
||||
}, |
||||
_downloadFile = function () { |
||||
var link = document.createElement('A'); |
||||
link.setAttribute('href', pswp.currItem.downloadURL || pswp.currItem.src || ''); |
||||
link.setAttribute('target', '_blank'); |
||||
link.setAttribute('download', ''); |
||||
|
||||
_downloadButton.appendChild(link); |
||||
link.click(); |
||||
_downloadButton.removeChild(link); |
||||
}, |
||||
_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 += |
||||
'<a href="' + |
||||
shareURL + |
||||
'" target="_blank" ' + |
||||
'class="pswp__share--' + |
||||
shareButtonData.id + |
||||
'"' + |
||||
(shareButtonData.download ? 'download' : '') + |
||||
'>' + |
||||
shareButtonData.label + |
||||
'</a>'; |
||||
|
||||
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; |
||||
var bars = _options.barsSize; |
||||
|
||||
if (_fitControlsInViewport()) { |
||||
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--download', |
||||
option: 'downloadEl', |
||||
onInit: function (el) { |
||||
_downloadButton = el; |
||||
}, |
||||
onTap: _downloadFile |
||||
}, |
||||
{ |
||||
name: 'button--zoom', |
||||
option: 'zoomEl', |
||||
onTap: pswp.toggleDesktopZoom |
||||
}, |
||||
{ |
||||
name: 'counter', |
||||
option: 'counterEl', |
||||
onInit: function (el) { |
||||
_indexIndicator = el; |
||||
} |
||||
}, |
||||
{ |
||||
name: 'button--close', |
||||
option: 'closeEl', |
||||
onTap: function () { |
||||
setTimeout(pswp.close); |
||||
} |
||||
}, |
||||
{ |
||||
name: 'button--arrow--left', |
||||
option: 'arrowEl', |
||||
onInit: function (el) { |
||||
_prevButton = el; |
||||
}, |
||||
onTap: pswp.prev |
||||
}, |
||||
{ |
||||
name: 'button--arrow--right', |
||||
option: 'arrowEl', |
||||
onInit: function (el) { |
||||
_nextButton = el; |
||||
}, |
||||
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.nodeType === 1 && |
||||
t.getAttribute('class') && |
||||
e.type.indexOf('mouse') > -1 && |
||||
(t.getAttribute('class').indexOf('__caption') > 0 || /(SMALL|STRONG|EM)/i.test(t.tagName)) |
||||
) { |
||||
preventObj.prevent = false; |
||||
_stopAllAnimations(); |
||||
} |
||||
}); |
||||
|
||||
// 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) { |
||||
var captionExists = _options.addCaptionHTMLFn(pswp.currItem, _captionContainer); |
||||
|
||||
_togglePswpClass(_captionContainer, 'caption--empty', !captionExists); |
||||
} |
||||
|
||||
_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(); |
||||
} |
||||
if (!_options.loop) { |
||||
if (pswp.getCurrentIndex() === 0) { |
||||
framework.addClass(_prevButton, 'pswp__element--disabled'); |
||||
} else { |
||||
framework.removeClass(_prevButton, 'pswp__element--disabled'); |
||||
} |
||||
if (pswp.getCurrentIndex() === _options.getNumItemsFn() - 1) { |
||||
framework.addClass(_nextButton, 'pswp__element--disabled'); |
||||
} else { |
||||
framework.removeClass(_nextButton, 'pswp__element--disabled'); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
ui.onGlobalTap = function (e) { |
||||
e = e || window.event; |
||||
var target = e.target || e.srcElement; |
||||
|
||||
if (_blockControlsTap) { |
||||
return; |
||||
} |
||||
|
||||
if (e.detail && e.detail.pointerType === 'mouse') { |
||||
// Silently ignore right-click events.
|
||||
if (!e.detail.rightClick) { |
||||
// close gallery if clicked outside of the image
|
||||
if (_options.closeOnOutsideClick && _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 if (_options.clickToShowNextNonZoomable) { |
||||
pswp.next(); |
||||
} |
||||
} 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') || (_options.closeOnOutsideClick && _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; |
||||
}); |
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,257 @@
|
||||
const defaultOptions = { |
||||
videoAttributes: { controls: '', playsinline: '', preload: 'auto' }, |
||||
autoplay: true, |
||||
|
||||
// prevent drag/swipe gesture over the bottom part of video
|
||||
// set to 0 to disable
|
||||
preventDragOffset: 40 |
||||
}; |
||||
|
||||
/** |
||||
* Check if slide has video content |
||||
* |
||||
* @param {Slide|Content} content Slide or Content object |
||||
* @returns Boolean |
||||
*/ |
||||
function isVideoContent(content) { |
||||
return (content && content.data && content.data.type === 'video'); |
||||
} |
||||
|
||||
class VideoContentSetup { |
||||
constructor(lightbox, options) { |
||||
this.options = options; |
||||
|
||||
this.initLightboxEvents(lightbox); |
||||
lightbox.on('init', () => { |
||||
this.initPswpEvents(lightbox.pswp); |
||||
}); |
||||
} |
||||
|
||||
initLightboxEvents(lightbox) { |
||||
lightbox.on('contentLoad', this.onContentLoad.bind(this)); |
||||
lightbox.on('contentDestroy', this.onContentDestroy.bind(this)); |
||||
lightbox.on('contentActivate', this.onContentActivate.bind(this)); |
||||
lightbox.on('contentDeactivate', this.onContentDeactivate.bind(this)); |
||||
lightbox.on('contentAppend', this.onContentAppend.bind(this)); |
||||
lightbox.on('contentResize', this.onContentResize.bind(this)); |
||||
|
||||
lightbox.addFilter('isKeepingPlaceholder', this.isKeepingPlaceholder.bind(this)); |
||||
lightbox.addFilter('isContentZoomable', this.isContentZoomable.bind(this)); |
||||
lightbox.addFilter('useContentPlaceholder', this.useContentPlaceholder.bind(this)); |
||||
|
||||
lightbox.addFilter('domItemData', (itemData, element, linkEl) => { |
||||
if (itemData.type === 'video' && linkEl) { |
||||
if (linkEl.dataset.pswpVideoSources) { |
||||
itemData.videoSources = JSON.parse(pswpVideoSources); |
||||
} else if (linkEl.dataset.pswpVideoSrc) { |
||||
itemData.videoSrc = linkEl.dataset.pswpVideoSrc; |
||||
} else { |
||||
itemData.videoSrc = linkEl.href; |
||||
} |
||||
} |
||||
return itemData; |
||||
}); |
||||
} |
||||
|
||||
initPswpEvents(pswp) { |
||||
// Prevent draggin when pointer is in bottom part of the video
|
||||
// todo: add option for this
|
||||
pswp.on('pointerDown', (e) => { |
||||
const slide = pswp.currSlide; |
||||
if (isVideoContent(slide) && this.options.preventDragOffset) { |
||||
const origEvent = e.originalEvent; |
||||
if (origEvent.type === 'pointerdown') { |
||||
const videoHeight = Math.ceil(slide.height * slide.currZoomLevel); |
||||
const verticalEnding = videoHeight + slide.bounds.center.y; |
||||
const pointerYPos = origEvent.pageY - pswp.offset.y; |
||||
if (pointerYPos > verticalEnding - this.options.preventDragOffset
|
||||
&& pointerYPos < verticalEnding) { |
||||
e.preventDefault(); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
|
||||
// do not append video on nearby slides
|
||||
pswp.on('appendHeavy', (e) => { |
||||
if (isVideoContent(e.slide) && !e.slide.isActive) { |
||||
e.preventDefault(); |
||||
} |
||||
}); |
||||
|
||||
pswp.on('close', () => { |
||||
if (isVideoContent(pswp.currSlide.content)) { |
||||
// Switch from zoom to fade closing transition,
|
||||
// as zoom transition is choppy for videos
|
||||
if (!pswp.options.showHideAnimationType |
||||
|| pswp.options.showHideAnimationType === 'zoom') { |
||||
pswp.options.showHideAnimationType = 'fade'; |
||||
} |
||||
|
||||
// pause video when closing
|
||||
this.pauseVideo(pswp.currSlide.content); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
onContentDestroy({ content }) { |
||||
if (isVideoContent(content)) { |
||||
if (content._videoPosterImg) { |
||||
content._videoPosterImg.onload = content._videoPosterImg.onerror = null; |
||||
content._videoPosterImg = null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
onContentResize(e) { |
||||
if (isVideoContent(e.content)) { |
||||
e.preventDefault(); |
||||
|
||||
const width = e.width; |
||||
const height = e.height; |
||||
const content = e.content; |
||||
|
||||
if (content.element) { |
||||
content.element.style.width = width + 'px'; |
||||
content.element.style.height = height + 'px'; |
||||
} |
||||
|
||||
if (content.slide && content.slide.placeholder) { |
||||
// override placeholder size, so it more accurately matches the video
|
||||
const placeholderElStyle = content.slide.placeholder.element.style; |
||||
placeholderElStyle.transform = 'none'; |
||||
placeholderElStyle.width = width + 'px'; |
||||
placeholderElStyle.height = height + 'px'; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
isKeepingPlaceholder(isZoomable, content) { |
||||
if (isVideoContent(content)) { |
||||
return false; |
||||
} |
||||
return isZoomable; |
||||
} |
||||
|
||||
isContentZoomable(isZoomable, content) { |
||||
if (isVideoContent(content)) { |
||||
return false; |
||||
} |
||||
return isZoomable; |
||||
} |
||||
|
||||
onContentActivate({ content }) { |
||||
if (isVideoContent(content) && this.options.autoplay) { |
||||
this.playVideo(content); |
||||
} |
||||
} |
||||
|
||||
onContentDeactivate({ content }) { |
||||
if (isVideoContent(content)) { |
||||
this.pauseVideo(content); |
||||
} |
||||
} |
||||
|
||||
onContentAppend(e) { |
||||
if (isVideoContent(e.content)) { |
||||
e.preventDefault(); |
||||
e.content.isAttached = true; |
||||
e.content.appendImage(); |
||||
} |
||||
} |
||||
|
||||
onContentLoad(e) { |
||||
const content = e.content; // todo: videocontent
|
||||
|
||||
if (!isVideoContent(e.content)) { |
||||
return; |
||||
} |
||||
|
||||
// stop default content load
|
||||
e.preventDefault(); |
||||
|
||||
if (content.element) { |
||||
return; |
||||
} |
||||
|
||||
content.state = 'loading'; |
||||
content.type = 'video'; // TODO: move this to pswp core?
|
||||
|
||||
content.element = document.createElement('video'); |
||||
|
||||
if (this.options.videoAttributes) { |
||||
for(let key in this.options.videoAttributes) { |
||||
content.element.setAttribute(key, this.options.videoAttributes[key] || ''); |
||||
} |
||||
} |
||||
|
||||
content.element.setAttribute('poster', content.data.msrc); |
||||
|
||||
this.preloadVideoPoster(content, content.data.msrc); |
||||
|
||||
content.element.style.position = 'absolute'; |
||||
content.element.style.left = 0; |
||||
content.element.style.top = 0; |
||||
|
||||
if (content.data.videoSources) { |
||||
content.data.videoSources.forEach((source) => { |
||||
let sourceEl = document.createElement('source'); |
||||
sourceEl.src = source.src; |
||||
sourceEl.type = source.type; |
||||
content.element.appendChild(sourceEl); |
||||
}); |
||||
} else if (content.data.videoSrc) { |
||||
// Force video preload
|
||||
// https://muffinman.io/blog/hack-for-ios-safari-to-display-html-video-thumbnail/
|
||||
// this.element.src = this.data.videoSrc + '#t=0.001';
|
||||
content.element.src = content.data.videoSrc; |
||||
} |
||||
} |
||||
|
||||
preloadVideoPoster(content, src) { |
||||
if (!content._videoPosterImg && src) { |
||||
content._videoPosterImg = new Image(); |
||||
content._videoPosterImg.src = src; |
||||
if (content._videoPosterImg.complete) { |
||||
content.onLoaded(); |
||||
} else { |
||||
content._videoPosterImg.onload = content._videoPosterImg.onerror = () => { |
||||
content.onLoaded(); |
||||
}; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
playVideo(content) { |
||||
if (content.element) { |
||||
content.element.play(); |
||||
} |
||||
} |
||||
|
||||
pauseVideo(content) { |
||||
if (content.element) { |
||||
content.element.pause(); |
||||
} |
||||
} |
||||
|
||||
useContentPlaceholder(usePlaceholder, content) { |
||||
if (isVideoContent(content)) { |
||||
return true; |
||||
} |
||||
return usePlaceholder; |
||||
} |
||||
|
||||
} |
||||
|
||||
class PhotoSwipeVideoPlugin { |
||||
constructor(lightbox, options) { |
||||
new VideoContentSetup(lightbox, { |
||||
...defaultOptions, |
||||
...options |
||||
}); |
||||
} |
||||
} |
||||
|
||||
export { PhotoSwipeVideoPlugin as default }; |
||||
@ -0,0 +1 @@
|
||||
const e={videoAttributes:{controls:"",playsinline:"",preload:"auto"},autoplay:!0,preventDragOffset:40};function t(e){return e&&e.data&&"video"===e.data.type}class o{constructor(e,t){this.options=t,this.initLightboxEvents(e),e.on("init",(()=>{this.initPswpEvents(e.pswp)}))}initLightboxEvents(e){e.on("contentLoad",this.onContentLoad.bind(this)),e.on("contentDestroy",this.onContentDestroy.bind(this)),e.on("contentActivate",this.onContentActivate.bind(this)),e.on("contentDeactivate",this.onContentDeactivate.bind(this)),e.on("contentAppend",this.onContentAppend.bind(this)),e.on("contentResize",this.onContentResize.bind(this)),e.addFilter("isKeepingPlaceholder",this.isKeepingPlaceholder.bind(this)),e.addFilter("isContentZoomable",this.isContentZoomable.bind(this)),e.addFilter("useContentPlaceholder",this.useContentPlaceholder.bind(this)),e.addFilter("domItemData",((e,t,o)=>("video"===e.type&&o&&(o.dataset.pswpVideoSources?e.videoSources=JSON.parse(pswpVideoSources):o.dataset.pswpVideoSrc?e.videoSrc=o.dataset.pswpVideoSrc:e.videoSrc=o.href),e)))}initPswpEvents(e){e.on("pointerDown",(o=>{const n=e.currSlide;if(t(n)&&this.options.preventDragOffset){const t=o.originalEvent;if("pointerdown"===t.type){const i=Math.ceil(n.height*n.currZoomLevel)+n.bounds.center.y,s=t.pageY-e.offset.y;s>i-this.options.preventDragOffset&&s<i&&o.preventDefault()}}})),e.on("appendHeavy",(e=>{t(e.slide)&&!e.slide.isActive&&e.preventDefault()})),e.on("close",(()=>{t(e.currSlide.content)&&(e.options.showHideAnimationType&&"zoom"!==e.options.showHideAnimationType||(e.options.showHideAnimationType="fade"),this.pauseVideo(e.currSlide.content))}))}onContentDestroy({content:e}){t(e)&&e._videoPosterImg&&(e._videoPosterImg.onload=e._videoPosterImg.onerror=null,e._videoPosterImg=null)}onContentResize(e){if(t(e.content)){e.preventDefault();const t=e.width,o=e.height,n=e.content;if(n.element&&(n.element.style.width=t+"px",n.element.style.height=o+"px"),n.slide&&n.slide.placeholder){const e=n.slide.placeholder.element.style;e.transform="none",e.width=t+"px",e.height=o+"px"}}}isKeepingPlaceholder(e,o){return!t(o)&&e}isContentZoomable(e,o){return!t(o)&&e}onContentActivate({content:e}){t(e)&&this.options.autoplay&&this.playVideo(e)}onContentDeactivate({content:e}){t(e)&&this.pauseVideo(e)}onContentAppend(e){t(e.content)&&(e.preventDefault(),e.content.isAttached=!0,e.content.appendImage())}onContentLoad(e){const o=e.content;if(t(e.content)&&(e.preventDefault(),!o.element)){if(o.state="loading",o.type="video",o.element=document.createElement("video"),this.options.videoAttributes)for(let e in this.options.videoAttributes)o.element.setAttribute(e,this.options.videoAttributes[e]||"");o.element.setAttribute("poster",o.data.msrc),this.preloadVideoPoster(o,o.data.msrc),o.element.style.position="absolute",o.element.style.left=0,o.element.style.top=0,o.data.videoSources?o.data.videoSources.forEach((e=>{let t=document.createElement("source");t.src=e.src,t.type=e.type,o.element.appendChild(t)})):o.data.videoSrc&&(o.element.src=o.data.videoSrc)}}preloadVideoPoster(e,t){!e._videoPosterImg&&t&&(e._videoPosterImg=new Image,e._videoPosterImg.src=t,e._videoPosterImg.complete?e.onLoaded():e._videoPosterImg.onload=e._videoPosterImg.onerror=()=>{e.onLoaded()})}playVideo(e){e.element&&e.element.play()}pauseVideo(e){e.element&&e.element.pause()}useContentPlaceholder(e,o){return!!t(o)||e}}class n{constructor(t,n){new o(t,{...e,...n})}}export{n as default}; |
||||
@ -1,175 +1,420 @@
|
||||
/*! PhotoSwipe main CSS by Dmitry Semenov | photoswipe.com | MIT license */ |
||||
/*! PhotoSwipe main CSS by Dmytro Semenov | photoswipe.com */ |
||||
|
||||
.pswp { |
||||
--pswp-bg: #000; |
||||
--pswp-placeholder-bg: #222; |
||||
|
||||
|
||||
--pswp-root-z-index: 100000; |
||||
|
||||
--pswp-preloader-color: rgba(79, 79, 79, 0.4); |
||||
--pswp-preloader-color-secondary: rgba(255, 255, 255, 0.9); |
||||
|
||||
/* defined via js: |
||||
--pswp-transition-duration: 333ms; */ |
||||
|
||||
--pswp-icon-color: #fff; |
||||
--pswp-icon-color-secondary: #4f4f4f; |
||||
--pswp-icon-stroke-color: #4f4f4f; |
||||
--pswp-icon-stroke-width: 2px; |
||||
|
||||
--pswp-error-text-color: var(--pswp-icon-color); |
||||
} |
||||
|
||||
|
||||
/* |
||||
Styles for basic PhotoSwipe functionality (sliding area, open/close transitions) |
||||
Styles for basic PhotoSwipe (pswp) functionality (sliding area, open/close transitions) |
||||
*/ |
||||
/* pswp = photoswipe */ |
||||
|
||||
.pswp { |
||||
display: none; |
||||
position: absolute; |
||||
width: 100%; |
||||
height: 100%; |
||||
left: 0; |
||||
top: 0; |
||||
overflow: hidden; |
||||
-ms-touch-action: none; |
||||
touch-action: none; |
||||
z-index: 16777271; |
||||
-webkit-text-size-adjust: 100%; |
||||
/* create separate layer, to avoid paint on window.onscroll in webkit/blink */ |
||||
-webkit-backface-visibility: hidden; |
||||
outline: none; } |
||||
.pswp * { |
||||
-webkit-box-sizing: border-box; |
||||
box-sizing: border-box; } |
||||
.pswp img { |
||||
max-width: none; } |
||||
|
||||
/* style is added when JS option showHideOpacity is set to true */ |
||||
.pswp--animate_opacity { |
||||
/* 0.001, because opacity:0 doesn't trigger Paint action, which causes lag at start of transition */ |
||||
opacity: 0.001; |
||||
will-change: opacity; |
||||
/* for open/close transition */ |
||||
-webkit-transition: opacity 333ms cubic-bezier(0.4, 0, 0.22, 1); |
||||
transition: opacity 333ms cubic-bezier(0.4, 0, 0.22, 1); } |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
z-index: var(--pswp-root-z-index); |
||||
display: none; |
||||
touch-action: none; |
||||
outline: 0; |
||||
opacity: 0.003; |
||||
contain: layout style size; |
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); |
||||
} |
||||
|
||||
/* Prevents focus outline on the root element, |
||||
(it may be focused initially) */ |
||||
.pswp:focus { |
||||
outline: 0; |
||||
} |
||||
|
||||
.pswp * { |
||||
box-sizing: border-box; |
||||
} |
||||
|
||||
.pswp img { |
||||
max-width: none; |
||||
} |
||||
|
||||
.pswp--open { |
||||
display: block; } |
||||
|
||||
.pswp--zoom-allowed .pswp__img { |
||||
/* autoprefixer: off */ |
||||
cursor: -webkit-zoom-in; |
||||
cursor: -moz-zoom-in; |
||||
cursor: zoom-in; } |
||||
|
||||
.pswp--zoomed-in .pswp__img { |
||||
/* autoprefixer: off */ |
||||
cursor: -webkit-grab; |
||||
cursor: -moz-grab; |
||||
cursor: grab; } |
||||
|
||||
.pswp--dragging .pswp__img { |
||||
/* autoprefixer: off */ |
||||
cursor: -webkit-grabbing; |
||||
cursor: -moz-grabbing; |
||||
cursor: grabbing; } |
||||
display: block; |
||||
} |
||||
|
||||
/* |
||||
Background is added as a separate element. |
||||
As animating opacity is much faster than animating rgba() background-color. |
||||
*/ |
||||
.pswp, |
||||
.pswp__bg { |
||||
position: absolute; |
||||
left: 0; |
||||
top: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
background: #000; |
||||
opacity: 0; |
||||
-webkit-transform: translateZ(0); |
||||
transform: translateZ(0); |
||||
-webkit-backface-visibility: hidden; |
||||
will-change: opacity; |
||||
/* for open/close transition */ |
||||
-webkit-transition: opacity 333ms cubic-bezier(0.4, 0, 0.22, 1); |
||||
transition: opacity 333ms cubic-bezier(0.4, 0, 0.22, 1); } |
||||
transform: translateZ(0); |
||||
will-change: opacity; |
||||
} |
||||
|
||||
.pswp__bg { |
||||
opacity: 0.005; |
||||
background: var(--pswp-bg); |
||||
} |
||||
|
||||
.pswp, |
||||
.pswp__scroll-wrap { |
||||
position: absolute; |
||||
left: 0; |
||||
top: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
overflow: hidden; } |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.pswp__scroll-wrap, |
||||
.pswp__bg, |
||||
.pswp__container, |
||||
.pswp__item, |
||||
.pswp__content, |
||||
.pswp__img, |
||||
.pswp__zoom-wrap { |
||||
-ms-touch-action: none; |
||||
touch-action: none; |
||||
position: absolute; |
||||
left: 0; |
||||
right: 0; |
||||
top: 0; |
||||
bottom: 0; } |
||||
position: absolute; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
/* Prevent selection and tap highlights */ |
||||
.pswp__container, |
||||
.pswp__img, |
||||
.pswp__zoom-wrap { |
||||
width: auto; |
||||
height: auto; |
||||
} |
||||
|
||||
.pswp--click-to-zoom.pswp--zoom-allowed .pswp__img { |
||||
cursor: -webkit-zoom-in; |
||||
cursor: -moz-zoom-in; |
||||
cursor: zoom-in; |
||||
} |
||||
|
||||
.pswp--click-to-zoom.pswp--zoomed-in .pswp__img { |
||||
cursor: move; |
||||
cursor: -webkit-grab; |
||||
cursor: -moz-grab; |
||||
cursor: grab; |
||||
} |
||||
|
||||
.pswp--click-to-zoom.pswp--zoomed-in .pswp__img:active { |
||||
cursor: -webkit-grabbing; |
||||
cursor: -moz-grabbing; |
||||
cursor: grabbing; |
||||
} |
||||
|
||||
/* :active to override grabbing cursor */ |
||||
.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img, |
||||
.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img:active, |
||||
.pswp__img { |
||||
-webkit-user-select: none; |
||||
-ms-user-select: none; |
||||
user-select: none; |
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); |
||||
-webkit-touch-callout: none; } |
||||
cursor: -webkit-zoom-out; |
||||
cursor: -moz-zoom-out; |
||||
cursor: zoom-out; |
||||
} |
||||
|
||||
.pswp__zoom-wrap { |
||||
position: absolute; |
||||
width: 100%; |
||||
-webkit-transform-origin: left top; |
||||
-ms-transform-origin: left top; |
||||
transform-origin: left top; |
||||
/* for open/close transition */ |
||||
-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--animated-in .pswp__bg, |
||||
.pswp--animated-in .pswp__zoom-wrap { |
||||
-webkit-transition: none; |
||||
transition: none; } |
||||
|
||||
/* Prevent selection and tap highlights */ |
||||
.pswp__container, |
||||
.pswp__zoom-wrap { |
||||
-webkit-backface-visibility: hidden; } |
||||
.pswp__img, |
||||
.pswp__button, |
||||
.pswp__counter { |
||||
-webkit-user-select: none; |
||||
-moz-user-select: none; |
||||
-ms-user-select: none; |
||||
user-select: none; |
||||
} |
||||
|
||||
.pswp__item { |
||||
position: absolute; |
||||
left: 0; |
||||
right: 0; |
||||
top: 0; |
||||
bottom: 0; |
||||
overflow: hidden; } |
||||
/* z-index for fade transition */ |
||||
z-index: 1; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.pswp__img { |
||||
.pswp__hidden { |
||||
display: none !important; |
||||
} |
||||
|
||||
/* Allow to click through pswp__content element, but not its children */ |
||||
.pswp__content { |
||||
pointer-events: none; |
||||
} |
||||
.pswp__content > * { |
||||
pointer-events: auto; |
||||
} |
||||
|
||||
|
||||
/* |
||||
|
||||
PhotoSwipe UI |
||||
|
||||
*/ |
||||
|
||||
/* |
||||
Error message appears when image is not loaded |
||||
(JS option errorMsg controls markup) |
||||
*/ |
||||
.pswp__error-msg-container { |
||||
display: grid; |
||||
} |
||||
.pswp__error-msg { |
||||
margin: auto; |
||||
font-size: 1em; |
||||
line-height: 1; |
||||
color: var(--pswp-error-text-color); |
||||
} |
||||
|
||||
/* |
||||
class pswp__hide-on-close is applied to elements that |
||||
should hide (for example fade out) when PhotoSwipe is closed |
||||
and show (for example fade in) when PhotoSwipe is opened |
||||
*/ |
||||
.pswp .pswp__hide-on-close { |
||||
opacity: 0.005; |
||||
will-change: opacity; |
||||
transition: opacity var(--pswp-transition-duration) cubic-bezier(0.4, 0, 0.22, 1); |
||||
z-index: 10; /* always overlap slide content */ |
||||
pointer-events: none; /* hidden elements should not be clickable */ |
||||
} |
||||
|
||||
/* class pswp--ui-visible is added when opening or closing transition starts */ |
||||
.pswp--ui-visible .pswp__hide-on-close { |
||||
opacity: 1; |
||||
pointer-events: auto; |
||||
} |
||||
|
||||
/* <button> styles, including css reset */ |
||||
.pswp__button { |
||||
position: relative; |
||||
display: block; |
||||
width: 50px; |
||||
height: 60px; |
||||
padding: 0; |
||||
margin: 0; |
||||
overflow: hidden; |
||||
cursor: pointer; |
||||
background: none; |
||||
border: 0; |
||||
box-shadow: none; |
||||
opacity: 0.85; |
||||
-webkit-appearance: none; |
||||
-webkit-touch-callout: none; |
||||
} |
||||
|
||||
.pswp__button:hover, |
||||
.pswp__button:active, |
||||
.pswp__button:focus { |
||||
transition: none; |
||||
padding: 0; |
||||
background: none; |
||||
border: 0; |
||||
box-shadow: none; |
||||
opacity: 1; |
||||
} |
||||
|
||||
.pswp__button:disabled { |
||||
opacity: 0.3; |
||||
cursor: auto; |
||||
} |
||||
|
||||
.pswp__icn { |
||||
fill: var(--pswp-icon-color); |
||||
color: var(--pswp-icon-color-secondary); |
||||
} |
||||
|
||||
.pswp__icn { |
||||
position: absolute; |
||||
width: auto; |
||||
height: auto; |
||||
top: 0; |
||||
left: 0; } |
||||
top: 14px; |
||||
left: 9px; |
||||
width: 32px; |
||||
height: 32px; |
||||
overflow: hidden; |
||||
pointer-events: none; |
||||
} |
||||
|
||||
.pswp__icn-shadow { |
||||
stroke: var(--pswp-icon-stroke-color); |
||||
stroke-width: var(--pswp-icon-stroke-width); |
||||
fill: none; |
||||
} |
||||
|
||||
.pswp__icn:focus { |
||||
outline: 0; |
||||
} |
||||
|
||||
/* |
||||
stretched thumbnail or div placeholder element (see below) |
||||
style is added to avoid flickering in webkit/blink when layers overlap |
||||
div element that matches size of large image, |
||||
large image loads on top of it, |
||||
used when msrc is not provided |
||||
*/ |
||||
.pswp__img--placeholder { |
||||
-webkit-backface-visibility: hidden; } |
||||
div.pswp__img--placeholder, |
||||
.pswp__img--with-bg { |
||||
background: var(--pswp-placeholder-bg); |
||||
} |
||||
|
||||
.pswp__top-bar { |
||||
position: absolute; |
||||
left: 0; |
||||
top: 0; |
||||
width: 100%; |
||||
height: 60px; |
||||
display: flex; |
||||
flex-direction: row; |
||||
justify-content: flex-end; |
||||
z-index: 10; |
||||
|
||||
/* allow events to pass through top bar itself */ |
||||
pointer-events: none !important; |
||||
} |
||||
.pswp__top-bar > * { |
||||
pointer-events: auto; |
||||
/* this makes transition significantly more smooth, |
||||
even though inner elements are not animated */ |
||||
will-change: opacity; |
||||
} |
||||
|
||||
|
||||
/* |
||||
div element that matches size of large image |
||||
large image loads on top of it |
||||
|
||||
Close button |
||||
|
||||
*/ |
||||
.pswp__img--placeholder--blank { |
||||
background: #222; } |
||||
.pswp__button--close { |
||||
margin-right: 6px; |
||||
} |
||||
|
||||
.pswp--ie .pswp__img { |
||||
width: 100% !important; |
||||
height: auto !important; |
||||
left: 0; |
||||
top: 0; } |
||||
|
||||
/* |
||||
Error message appears when image is not loaded |
||||
(JS option errorMsg controls markup) |
||||
|
||||
Arrow buttons |
||||
|
||||
*/ |
||||
.pswp__error-msg { |
||||
.pswp__button--arrow { |
||||
position: absolute; |
||||
left: 0; |
||||
top: 0; |
||||
width: 75px; |
||||
height: 100px; |
||||
top: 50%; |
||||
width: 100%; |
||||
text-align: center; |
||||
margin-top: -50px; |
||||
} |
||||
|
||||
.pswp__button--arrow:disabled { |
||||
display: none; |
||||
cursor: default; |
||||
} |
||||
|
||||
.pswp__button--arrow .pswp__icn { |
||||
top: 50%; |
||||
margin-top: -30px; |
||||
width: 60px; |
||||
height: 60px; |
||||
background: none; |
||||
border-radius: 0; |
||||
} |
||||
|
||||
.pswp--one-slide .pswp__button--arrow { |
||||
display: none; |
||||
} |
||||
|
||||
/* hide arrows on touch screens */ |
||||
.pswp--touch .pswp__button--arrow { |
||||
visibility: hidden; |
||||
} |
||||
|
||||
/* show arrows only after mouse was used */ |
||||
.pswp--has_mouse .pswp__button--arrow { |
||||
visibility: visible; |
||||
} |
||||
|
||||
.pswp__button--arrow--prev { |
||||
right: auto; |
||||
left: 0px; |
||||
} |
||||
|
||||
.pswp__button--arrow--next { |
||||
right: 0px; |
||||
} |
||||
.pswp__button--arrow--next .pswp__icn { |
||||
left: auto; |
||||
right: 14px; |
||||
/* flip horizontally */ |
||||
transform: scale(-1, 1); |
||||
} |
||||
|
||||
/* |
||||
|
||||
Zoom button |
||||
|
||||
*/ |
||||
.pswp__button--zoom { |
||||
display: none; |
||||
} |
||||
|
||||
.pswp--zoom-allowed .pswp__button--zoom { |
||||
display: block; |
||||
} |
||||
|
||||
/* "+" => "-" */ |
||||
.pswp--zoomed-in .pswp__zoom-icn-bar-v { |
||||
display: none; |
||||
} |
||||
|
||||
|
||||
/* |
||||
|
||||
Loading indicator |
||||
|
||||
*/ |
||||
.pswp__preloader { |
||||
position: relative; |
||||
overflow: hidden; |
||||
width: 50px; |
||||
height: 60px; |
||||
margin-right: auto; |
||||
} |
||||
|
||||
.pswp__preloader .pswp__icn { |
||||
opacity: 0; |
||||
transition: opacity 0.2s linear; |
||||
animation: pswp-clockwise 600ms linear infinite; |
||||
} |
||||
|
||||
.pswp__preloader--active .pswp__icn { |
||||
opacity: 0.85; |
||||
} |
||||
|
||||
@keyframes pswp-clockwise { |
||||
0% { transform: rotate(0deg); } |
||||
100% { transform: rotate(360deg); } |
||||
} |
||||
|
||||
|
||||
/* |
||||
|
||||
"1 of 10" counter |
||||
|
||||
*/ |
||||
.pswp__counter { |
||||
height: 30px; |
||||
margin-top: 15px; |
||||
margin-inline-start: 20px; |
||||
font-size: 14px; |
||||
line-height: 16px; |
||||
margin-top: -8px; |
||||
color: #ccc; } |
||||
line-height: 30px; |
||||
color: var(--pswp-icon-color); |
||||
text-shadow: 1px 1px 3px var(--pswp-icon-color-secondary); |
||||
opacity: 0.85; |
||||
} |
||||
|
||||
.pswp__error-msg a { |
||||
color: #ccc; |
||||
text-decoration: underline; } |
||||
.pswp--one-slide .pswp__counter { |
||||
display: none; |
||||
} |
||||
|
||||
@ -1,10 +0,0 @@
|
||||
{ |
||||
"version": 3, |
||||
"file": "photoswipe.css", |
||||
"sources": [ |
||||
"../src/css/main.scss", |
||||
"../src/css/_main-settings.scss" |
||||
], |
||||
"names": [], |
||||
"mappings": "AAAA,2EAA2E;AAE3E;;EAEE;AAMF,uBAAuB;AACvB,AAAA,KAAK,CAAC;EACL,OAAO,EAAE,IAAI;EACb,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,IAAI,EAAE,CAAC;EACP,GAAG,EAAE,CAAC;EACN,QAAQ,EAAE,MAAM;EAChB,gBAAgB,EAAE,IAAI;EACtB,YAAY,EAAE,IAAI;EAClB,OAAO,EChBa,QAAQ;EDiB5B,wBAAwB,EAAE,IAAI;EAC9B,8EAA8E;EAC9E,2BAA2B,EAAE,MAAM;EACnC,OAAO,EAAE,IAAI,GAWb;EAzBD,AAiBE,KAjBG,CAiBH,CAAC,CAAC;IACD,UAAU,EAAE,UAAU,GACtB;EAnBH,AAsBC,KAtBI,CAsBJ,GAAG,CAAC;IACH,SAAS,EAAE,IAAI,GACf;;AAGF,kEAAkE;AAClE,AAAA,sBAAsB,CAAC;EACtB,oGAAoG;EACpG,OAAO,EAAE,KAAK;EACd,WAAW,EAAE,OAAO;EACpB,+BAA+B;EAC/B,UAAU,EAAE,OAAO,CC5CkB,KAAK,CD4Ce,6BAA6B,GACtF;;AAED,AAAA,WAAW,CAAC;EACX,OAAO,EAAE,KAAK,GACd;;AAED,AAAA,mBAAmB,CAAC,UAAU,CAAC;EAC9B,uBAAuB;EACvB,MAAM,EAAE,eAAe;EACvB,MAAM,EAAE,YAAY;EACpB,MAAM,EAAE,OAAO,GACf;;AAED,AAAA,gBAAgB,CAAC,UAAU,CAAC;EAC3B,uBAAuB;EACvB,MAAM,EAAE,YAAY;EACpB,MAAM,EAAE,SAAS;EACjB,MAAM,EAAE,IAAI,GACZ;;AAED,AAAA,eAAe,CAAC,UAAU,CAAC;EAC1B,uBAAuB;EACvB,MAAM,EAAE,gBAAgB;EACxB,MAAM,EAAE,aAAa;EACrB,MAAM,EAAE,QAAQ,GAChB;;AAED;;;EAGE;AACF,AAAA,SAAS,CAAC;EACT,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,CAAC;EACP,GAAG,EAAE,CAAC;EACN,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,UAAU,EChFc,IAAI;EDiF5B,OAAO,EAAE,CAAC;EACV,SAAS,EAAE,aAAa;EACxB,2BAA2B,EAAE,MAAM;EACnC,WAAW,EAAE,OAAO;EACpB,+BAA+B;EAC/B,UAAU,EAAE,OAAO,CCxFkB,KAAK,CDwFe,6BAA6B,GACtF;;AAED,AAAA,kBAAkB,CAAC;EAClB,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,CAAC;EACP,GAAG,EAAE,CAAC;EACN,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,QAAQ,EAAE,MAAM,GAChB;;AAED,AAAA,gBAAgB;AAChB,gBAAgB,CAAC;EAChB,gBAAgB,EAAE,IAAI;EACtB,YAAY,EAAE,IAAI;EAClB,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,GAAG,EAAE,CAAC;EACN,MAAM,EAAE,CAAC,GACT;;AAED,0CAA0C;AAC1C,AAAA,gBAAgB;AAChB,UAAU,CAAC;EACV,mBAAmB,EAAE,IAAI;EACzB,gBAAgB,EAAE,IAAI;EACtB,WAAW,EAAE,IAAI;EACjB,2BAA2B,EAAE,gBAAgB;EAC7C,qBAAqB,EAAE,IAAI,GAC3B;;AAED,AAAA,gBAAgB,CAAC;EAChB,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;EACX,wBAAwB,EAAE,QAAQ;EAClC,qBAAqB,EAAE,QAAQ;EAC/B,oBAAoB,EAAE,QAAQ;EAC9B,gBAAgB,EAAE,QAAQ;EAC1B,+BAA+B;EAC/B,UAAU,EAAE,SAAS,CCjIgB,KAAK,CDiIiB,6BAA6B,GACxF;;AAED,AACC,kBADiB,CACjB,SAAS;AADV,kBAAkB,CAEjB,gBAAgB,CAAC;EAChB,kBAAkB,EAAE,IAAI;EACxB,UAAU,EAAE,IAAI,GAChB;;AAGF,AAAA,gBAAgB;AAChB,gBAAgB,CAAC;EAChB,2BAA2B,EAAE,MAAM,GACnC;;AAED,AAAA,WAAW,CAAC;EACX,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,GAAG,EAAE,CAAC;EACN,MAAM,EAAE,CAAC;EACT,QAAQ,EAAE,MAAM,GAChB;;AAED,AAAA,UAAU,CAAC;EACV,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,GAAG,EAAE,CAAC;EACN,IAAI,EAAE,CAAC,GACP;;AAED;;;EAGE;AACF,AAAA,uBAAuB,CAAC;EACvB,2BAA2B,EAAE,MAAM,GACnC;;AAED;;;EAGE;AACF,AAAA,8BAA8B,CAAC;EAC9B,UAAU,EC5Ke,IAAI,GD6K7B;;AAED,AAAA,SAAS,CAAC,UAAU,CAAC;EACpB,KAAK,EAAE,eAAe;EACtB,MAAM,EAAE,eAAe;EACvB,IAAI,EAAE,CAAC;EACP,GAAG,EAAE,CAAC,GACN;;AAED;;;EAGE;AACF,AAAA,gBAAgB,CAAC;EAChB,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,CAAC;EACP,GAAG,EAAE,GAAG;EACR,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,MAAM;EAClB,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,IAAI;EAChB,KAAK,EC/LmB,IAAI,GDgM5B;;AAED,AAAA,gBAAgB,CAAC,CAAC,CAAC;EAClB,KAAK,ECnMmB,IAAI;EDoM5B,eAAe,EAAE,SAAS,GAC1B" |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,98 +1,93 @@
|
||||
{% from 'description.html' import img_description %} |
||||
{% extends "base.html" %} |
||||
|
||||
{% block extra_head %} |
||||
<script src="{{ theme.url }}/photoswipe.min.js"></script> |
||||
<script src="{{ theme.url }}/photoswipe-ui-default.min.js"></script> |
||||
<script src="{{ theme.url }}/echo/echo.min.js"></script> |
||||
<link rel="stylesheet" href="{{ theme.url }}/photoswipe.css"> |
||||
<link rel="stylesheet" href="{{ theme.url }}/default-skin/default-skin.css"> |
||||
<script type="module"> |
||||
import PhotoSwipeLightbox from '/static/photoswipe-lightbox.esm.min.js'; |
||||
import PhotoSwipe from '/static/photoswipe.esm.min.js'; |
||||
import PhotoSwipeDynamicCaption from '/static/photoswipe-dynamic-caption-plugin.esm.min.js'; |
||||
import PhotoSwipeFullscreen from '/static/photoswipe-fullscreen.esm.min.js'; |
||||
import PhotoSwipeVideoPlugin from '/static/photoswipe-video-plugin.esm.min.js'; |
||||
|
||||
const lightbox = new PhotoSwipeLightbox({ |
||||
gallery: '.gallery', |
||||
children: '.thumbnail', |
||||
pswpModule: PhotoSwipe |
||||
}); |
||||
const captionPlugin = new PhotoSwipeDynamicCaption(lightbox, {type: 'auto'}); |
||||
const fullscreenPlugin = new PhotoSwipeFullscreen(lightbox); |
||||
const videoPlugin = new PhotoSwipeVideoPlugin(lightbox, {autoplay: true}); |
||||
|
||||
lightbox.on('uiRegister', function() { |
||||
lightbox.pswp.ui.registerElement({ |
||||
name: 'download-button', |
||||
order: 8, |
||||
isButton: true, |
||||
tagName: 'a', |
||||
html: { |
||||
isCustomSVG: true, |
||||
inner: '<path d="M20.5 14.3 17.1 18V10h-2.2v7.9l-3.4-3.6L10 16l6 6.1 6-6.1ZM23 23H9v2h14Z" id="pswp__icn-download"/>', |
||||
outlineID: 'pswp__icn-download' |
||||
}, |
||||
onInit: (el, pswp) => { |
||||
el.setAttribute('download', ''); |
||||
el.setAttribute('target', '_blank'); |
||||
el.setAttribute('rel', 'noopener'); |
||||
pswp.on('change', () => { |
||||
if (pswp.currSlide.data.element.children[0].dataset.big) { |
||||
el.href = pswp.currSlide.data.element.children[0].dataset.big; |
||||
} else { |
||||
el.href = pswp.currSlide.data.src; |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
}); |
||||
|
||||
lightbox.init(); |
||||
</script> |
||||
{% endblock extra_head %} |
||||
|
||||
{% block content %} |
||||
{% include 'download_zip.html' %} |
||||
{% include 'map.html' %} |
||||
<div class="gallery" itemscope itemtype="http://schema.org/ImageGallery"> |
||||
<div class="gallery"> |
||||
{% for media in album.medias %} |
||||
{% if media.type == "image" %} |
||||
<figure class="gallery__img--{{ "main" if loop.first else "secondary" }} thumbnail" |
||||
itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject"> |
||||
<a href="{{ media.url }}" itemprop="contentUrl" data-size="{{media.size.width}}x{{media.size.height}}"> |
||||
<img src="{{ theme.url }}/echo/blank.gif" |
||||
data-echo="{{ media.url if loop.first else media.thumbnail }}" |
||||
alt="{{ media.url }}" itemprop="thumbnail" title="{{ media.exif.datetime }}" /> |
||||
<figure class="gallery__img--{{ "main" if loop.first else "secondary" }} thumbnail"> |
||||
<a href="{{ media.url }}" |
||||
data-pswp-width="{{media.size.width}}" |
||||
data-pswp-height="{{media.size.height}}" |
||||
{%- if media.big -%} |
||||
data-big="{{ media.big_url }}" |
||||
{%- endif -%} |
||||
> |
||||
<img src="{{ media.thumbnail }}" alt="{{ media.url }}" /> |
||||
</a> |
||||
<figcaption itemprop="caption description">{{ media.title }} - {{ media.exif.datetime }}</figcaption> |
||||
<div class="pswp-caption-content"> |
||||
{{ img_description(media, with_big=False) }} |
||||
</div> |
||||
<figcaption>{{ media.title }} - {{ media.exif.datetime }}</figcaption> |
||||
</figure> |
||||
{% endif %} |
||||
{% if media.type == "video" %} |
||||
<figure class="gallery__img--secondary thumbnail" |
||||
itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject"> |
||||
<a href="{{ media.url }}" itemprop="contentUrl" data-type="video" |
||||
data-video='<div class="video"><div class="video__container"><video controls><source src="{{ media.url }}" type="{{ media.mime }}" /></video></div></div>'> |
||||
<img src="{{ theme.url }}/echo/blank.gif" |
||||
data-echo="{{ media.thumbnail }}" |
||||
alt="{{ media.thumbnail }}" itemprop="thumbnail" title="" /> |
||||
<figure class="gallery__img--secondary thumbnail" > |
||||
<a href="{{ media.url }}" |
||||
data-pswp-type="video" |
||||
data-pswp-width="800" |
||||
data-pswp-height="600"> |
||||
<img src="{{ media.thumbnail }}" alt="{{ media.url }}" /> |
||||
</a> |
||||
<figcaption itemprop="caption description">{{ media_title }}</figcaption> |
||||
<div class="pswp-caption-content"> |
||||
{{ img_description(media, with_big=False) }} |
||||
</div> |
||||
<figcaption>{{ media_title }}</figcaption> |
||||
</figure> |
||||
{% endif %} |
||||
{% endfor %} |
||||
</div> |
||||
|
||||
{% endblock %} |
||||
|
||||
{% block extra_footer %} |
||||
<!-- Root element of PhotoSwipe. Must have class pswp. --> |
||||
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true"> |
||||
<!-- Background of PhotoSwipe. |
||||
It's a separate element as animating opacity is faster than rgba(). --> |
||||
<div class="pswp__bg"></div> |
||||
|
||||
<!-- Slides wrapper with overflow:hidden. --> |
||||
<div class="pswp__scroll-wrap"> |
||||
<!-- Container that holds slides. |
||||
PhotoSwipe keeps only 3 of them in the DOM to save memory. |
||||
Don't modify these 3 pswp__item elements, data is added later on. --> |
||||
<div class="pswp__container"> |
||||
<div class="pswp__item"></div> |
||||
<div class="pswp__item"></div> |
||||
<div class="pswp__item"></div> |
||||
</div> |
||||
|
||||
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. --> |
||||
<div class="pswp__ui pswp__ui--hidden"> |
||||
<div class="pswp__top-bar"> |
||||
<!-- Controls are self-explanatory. Order can be changed. --> |
||||
<div class="pswp__counter"></div> |
||||
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button> |
||||
<button class="pswp__button pswp__button--share" title="Share"></button> |
||||
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button> |
||||
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button> |
||||
|
||||
<!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR --> |
||||
<!-- element will get class pswp__preloader-active when preloader is running --> |
||||
<div class="pswp__preloader"> |
||||
<div class="pswp__preloader__icn"> |
||||
<div class="pswp__preloader__cut"> |
||||
<div class="pswp__preloader__donut"></div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"> |
||||
<div class="pswp__share-tooltip"></div> |
||||
</div> |
||||
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"> |
||||
</button> |
||||
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"> |
||||
</button> |
||||
<div class="pswp__caption"> |
||||
<div class="pswp__caption__center"></div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<script src="{{ theme.url }}/app.js"></script> |
||||
|
||||
{% endblock %} |
||||
|
||||
Loading…
Reference in new issue