I'm trying to add a delete button overlayed on my thumbnails but when I click it the gallery is opened.
I tried adding this to try to stop the click propagating to the figure element but it didn't work:
$('body').on('click', '.delete-file-btn', function(e) {
e.preventDefault();
e.stopImmediatePropagation();
});
var initPhotoSwipeFromDOM = function(gallerySelector) {
// parse slide data (url, title, size ...) from DOM elements
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
size = linkEl.getAttribute('data-size').split('x');
// create slide object
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('src');
}
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 );
}
};
initPhotoSwipeFromDOM('.existing-files');
.existing-files {
margin: 1rem -.5rem;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.existing-files .file-container {
padding: .5rem;
text-align: center;
display: inline-block;
position: relative;
}
.delete-file-btn {
font-size: 0;
position: absolute;
display: block;
transform: scale(1);
width: 22px;
height: 22px;
border-radius: 40px;
background-color: #E2E8F0;
top: -1px;
right: -5px;
z-index: 100;
box-shadow: -2px 2px 6px 1px rgba(0, 0, 0, 0.25);
transition: background-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
.delete-file-btn::after, .delete-file-btn::before {
content: "";
display: block;
position: absolute;
width: 12px;
height: 2px;
background-color: #000000;
transform: rotate(45deg);
border-radius: 5px;
top: 10px;
left: 5px;
transition: background-color .15s ease-in-out;
}
.delete-file-btn::after {
transform: rotate(-45deg);
}
.delete-file-btn:hover, .delete-file-btn:focus, .delete-file-btn:active {
box-shadow: none;
background-color: #A0AEC0;
}
.delete-file-btn:hover::after, .delete-file-btn:hover::before, .delete-file-btn:focus::after, .delete-file-btn:focus::before, .delete-file-btn:active::after, .delete-file-btn:active::before {
background-color: #FFFFFF;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.js"></script>
<div class="existing-files">
<figure class="file-container">
<a data-size="304x171" data-turbolinks="false" class="gal" href="https://placeimg.com/304/171/nature"><img src="https://placeimg.com/304/171/nature"></a>
<a class="delete-file-btn" rel="nofollow" data-method="delete" href="#"></a>
</figure>
<figure class="file-container">
<a data-size="304x171" data-turbolinks="false" class="gal" href="https://placeimg.com/304/171/nature"><img src="https://placeimg.com/304/171/nature"></a>
<a class="delete-file-btn" rel="nofollow" data-method="delete" href="#"></a>
</figure>
</div>
<!-- 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 https://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>
Instead of preventing the click from propagating on elements it shouldn't I changed the script to only allow clicks on my gallery image anchor element class="gal" above. Here's the edited function from the script above.
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() === 'A' && el.className == 'gal');
});
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.parentNode,
childNodes = clickedListItem.parentNode.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.parentNode) {
index = nodeIndex;
break;
}
nodeIndex++;
}
if(index >= 0) {
// open PhotoSwipe if valid index found
openPhotoSwipe( index, clickedGallery );
}
return false;
};
Related
I have some simple vanilla accordion and I'm not really sure why the CSS transition is not applying here? The divs have correct height, what is going on here?
(Cannot post because apparently my issue is mostly code, so this text is a dirty fix, sorry).
HTML (simplified version)
<div class="container">
<ul>
<li class="accordion-item">
<button class="accordion-item__title">
Title
</button>
<div class="accordion-item__body not-active">
Body
</div>
</li>
</ul>
</div>
JS
document.addEventListener('DOMContentLoaded', function () {
const accordions = document.querySelectorAll('.block-accordion');
if (typeof (accordions) !== 'undefined' && accordions != null) {
//loop thorugh all acordions
for (let a = 0; a < accordions.length; a++) {
const accordion = accordions[a];
const accordionItems = accordion.querySelectorAll('.accordion-item');
//loop through all accordiond's items
for (let i = 0; i < accordionItems.length; i++) {
const accordionItem = accordionItems[i];
//show first by default
accordionItems[0].querySelector('.accordion-item__body').classList.remove('not-active');
accordionItems[0].querySelector('.accordion-item__body').parentElement.classList.add('active');
accordionItems[0].querySelector('.accordion-item__title').setAttribute("aria-expanded", true);
//hide each accordion on click
const accordionItemTitle = accordionItem.firstElementChild;
accordionItemTitle.addEventListener('click', function toggleAccordion(e) {
const accordionContent = accordionItem.querySelector('.accordion-item__body');
accordionContent.style.height = "auto";
if (accordionContent.previousElementSibling === e.target) {
accordionContent.classList.toggle('not-active');
accordionContent.parentElement.classList.toggle('active');
if (accordionContent.classList.contains('not-active')) {
accordionContent.style.height = '0px';
accordionContent.previousElementSibling.setAttribute("aria-expanded", false);
} else {
accordionContent.style.height = accordionContent.clientHeight + 'px';
accordionContent.previousElementSibling.setAttribute("aria-expanded", true);
}
}
});
}
}
}
});
SASS
.block-accordion {
.active {
display: block;
}
.not-active {
display: none;
transition: height 0.35s ease-in-out;
overflow: hidden;
}
}
Im trying to use a array who contains 4 diferent maps.
The first element of the array must be "sticked" and change the current element of the array by clicking next.
The next button when it reaches to the last item of the array must be showed disabled.
The previous button is disabled and when the next is clicked it should be unabled.
Im pretty lost right now any suggestion or advice will be very welcomed
var i = 0;
var mapsArray = [
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d209569.44700750793!2d-56.380275318336025!3d-34.84309361411796!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x959f802b6753b221%3A0x3257eb39860f05a6!2sPalacio%20Salvo!5e0!3m2!1sen!2suy!4v1614269355326!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d92110.09563909167!2d17.958933187703266!3d59.32686333113927!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x465f763119640bcb%3A0xa80d27d3679d7766!2sStockholm%2C%20Sweden!5e0!3m2!1sen!2suy!4v1614704350417!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d88989.45462143555!2d15.9390973!3d45.8128514!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4765d701f8ef1d1d%3A0x312b512f1e7f6df9!2sCathedral%20of%20Zagreb!5e0!3m2!1sen!2suy!4v1614704668458!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d6709.917127499258!2d-78.51409209928569!3d0.3576385746900253!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8e2a5da2881494ab%3A0xae89047fc027c897!2sapuela%20imbabura%20intac!5e0!3m2!1sen!2suy!4v1614704741586!5m2!1sen!2suy"
];
document.getElementById('myIframe').src = mapsArray[Math.floor(Math.random() * mapsArray.length)];
const prevBtn = document.querySelector(".prev");
const nextBtn = document.querySelector(".next");
function nextBtn() {
i = i + 1;
i = i % mapsArray.length;
return mapsArray[i];
}
function prevBtn() {
if (i === 0) {
i = mapsArray.length;
}
i = i - 1;
return mapsArray[i]
}
.maps {
display: flex;
justify-content: center;
align-items: center;
}
#myIframe {
width: 600px;
height: 600px;
}
<div class="maps">
<iframe id='myIframe' class="maps-gallery active"></iframe>
</div>
<div class="btns">
<button disabled onclick="nextBtn()" class="btn prev">Prev</button>
<button onclick="prevBtn()" class="btn next">Next</button>
you can not have button name and function calling the same name hence the error in console.
save your iframe in variable and then do iFrame.src = mapsArray[i] inside both back and next functions.
Check the index numbers in functions and accordingly disable the buttons based on first/last/middle number of index array.
var i = 0;
var mapsArray = [
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d209569.44700750793!2d-56.380275318336025!3d-34.84309361411796!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x959f802b6753b221%3A0x3257eb39860f05a6!2sPalacio%20Salvo!5e0!3m2!1sen!2suy!4v1614269355326!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d92110.09563909167!2d17.958933187703266!3d59.32686333113927!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x465f763119640bcb%3A0xa80d27d3679d7766!2sStockholm%2C%20Sweden!5e0!3m2!1sen!2suy!4v1614704350417!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d88989.45462143555!2d15.9390973!3d45.8128514!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4765d701f8ef1d1d%3A0x312b512f1e7f6df9!2sCathedral%20of%20Zagreb!5e0!3m2!1sen!2suy!4v1614704668458!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d6709.917127499258!2d-78.51409209928569!3d0.3576385746900253!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8e2a5da2881494ab%3A0xae89047fc027c897!2sapuela%20imbabura%20intac!5e0!3m2!1sen!2suy!4v1614704741586!5m2!1sen!2suy"
];
let iFrame = document.getElementById('myIframe')
iFrame.src = mapsArray[Math.floor(Math.random() * mapsArray.length)];
const prevB = document.querySelector(".prev");
const nextB = document.querySelector(".next");
function nextBtn() {
console.clear()
if (i >= 0 && i < 3) {
iFrame.src = mapsArray[i]
prevB.disabled = false
console.log("next button array index set:" + i)
i++
} else {
iFrame.src = mapsArray[i]
nextB.disabled = true
console.log("next button array index set:" + i)
i++
}
}
function prevBtn() {
if (i === 0) {
i = mapsArray.length;
}
i = i - 1;
console.clear()
console.log("prev array index:" + i)
if (i <= 3 && i > 0) {
iFrame.src = mapsArray[i]
nextB.disabled = false
} else {
iFrame.src = mapsArray[i]
prevB.disabled = true
}
}
.maps {
display: flex;
justify-content: center;
align-items: center;
}
#myIframe {
width: 150px;
height: 150px;
}
<div class="maps">
<iframe id='myIframe' class="maps-gallery active"></iframe>
</div>
<div class="btns">
<button disabled onclick="prevBtn()" class="btn prev">Prev</button>
<button onclick="nextBtn()" class="btn next">Next</button>
</div>
This should work:
var mapsArray = [
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d209569.44700750793!2d-56.380275318336025!3d-34.84309361411796!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x959f802b6753b221%3A0x3257eb39860f05a6!2sPalacio%20Salvo!5e0!3m2!1sen!2suy!4v1614269355326!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d92110.09563909167!2d17.958933187703266!3d59.32686333113927!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x465f763119640bcb%3A0xa80d27d3679d7766!2sStockholm%2C%20Sweden!5e0!3m2!1sen!2suy!4v1614704350417!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d88989.45462143555!2d15.9390973!3d45.8128514!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4765d701f8ef1d1d%3A0x312b512f1e7f6df9!2sCathedral%20of%20Zagreb!5e0!3m2!1sen!2suy!4v1614704668458!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d6709.917127499258!2d-78.51409209928569!3d0.3576385746900253!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8e2a5da2881494ab%3A0xae89047fc027c897!2sapuela%20imbabura%20intac!5e0!3m2!1sen!2suy!4v1614704741586!5m2!1sen!2suy"
];
var i = Math.floor(Math.random() * mapsArray.length);
var iFrameElement = document.getElementById('myiFrame')
iFrameElement .src = mapsArray[i];
function nextBtn() {
if (i === mapsArray.length) i = 0;
else i += 1;
iFrameElement.src = mapsArray[i];
}
function prevBtn() {
if (i === 0) i = mapsArray.length;
else i -= 1;
iFrameElement.src = mapsArray[i];
}
.maps {
display: flex;
justify-content: center;
align-items: center;
}
#myiFrame {
width: 600px;
height: 600px;
}
<div class="maps">
<iframe id="myiFrame"></iframe>
</div>
<div class="btns">
<button onclick="nextBtn()">Prev</button>
<button onclick="prevBtn()">Next</button>
</div>
Here is a simple approach -->
var mapsArray = [
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d209569.44700750793!2d-56.380275318336025!3d-34.84309361411796!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x959f802b6753b221%3A0x3257eb39860f05a6!2sPalacio%20Salvo!5e0!3m2!1sen!2suy!4v1614269355326!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d92110.09563909167!2d17.958933187703266!3d59.32686333113927!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x465f763119640bcb%3A0xa80d27d3679d7766!2sStockholm%2C%20Sweden!5e0!3m2!1sen!2suy!4v1614704350417!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d88989.45462143555!2d15.9390973!3d45.8128514!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4765d701f8ef1d1d%3A0x312b512f1e7f6df9!2sCathedral%20of%20Zagreb!5e0!3m2!1sen!2suy!4v1614704668458!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d6709.917127499258!2d-78.51409209928569!3d0.3576385746900253!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8e2a5da2881494ab%3A0xae89047fc027c897!2sapuela%20imbabura%20intac!5e0!3m2!1sen!2suy!4v1614704741586!5m2!1sen!2suy"
];
var index = 0;
const _prevBtn = document.querySelector(".prev");
const _nextBtn = document.querySelector(".next");
update();
function update() {
document.getElementById('myIframe').src = mapsArray[index];
btnDisableCheck();
}
function nextBtn() {
if (index < mapsArray.length - 1) {
index++;
_prevBtn.disabled = false;
update();
}
}
function prevBtn() {
if (index > 0) {
index--;
_nextBtn.disabled = false;
update();
}
}
function btnDisableCheck() {
if (index == 0)
_prevBtn.disabled = true;
if (index == mapsArray.length - 1)
_nextBtn.disabled = true;
}
<iframe id='myIframe' class="maps-gallery active"></iframe>
<button onclick="prevBtn()" class="btn prev">Prev</button>
<button onclick="nextBtn()" class="btn next">Next</button>
I think this is what you want, but i had to change a few things:
var mapsArray = [
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d209569.44700750793!2d-56.380275318336025!3d-34.84309361411796!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x959f802b6753b221%3A0x3257eb39860f05a6!2sPalacio%20Salvo!5e0!3m2!1sen!2suy!4v1614269355326!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d92110.09563909167!2d17.958933187703266!3d59.32686333113927!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x465f763119640bcb%3A0xa80d27d3679d7766!2sStockholm%2C%20Sweden!5e0!3m2!1sen!2suy!4v1614704350417!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d88989.45462143555!2d15.9390973!3d45.8128514!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4765d701f8ef1d1d%3A0x312b512f1e7f6df9!2sCathedral%20of%20Zagreb!5e0!3m2!1sen!2suy!4v1614704668458!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d6709.917127499258!2d-78.51409209928569!3d0.3576385746900253!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8e2a5da2881494ab%3A0xae89047fc027c897!2sapuela%20imbabura%20intac!5e0!3m2!1sen!2suy!4v1614704741586!5m2!1sen!2suy"
];
var myIframe = document.getElementById('myIframe');
var prevButton = document.getElementById('prevBtn');
var nextButton = document.getElementById('nextBtn');
var i = Math.floor(Math.random() * mapsArray.length);
function update() {
myIframe.src = mapsArray[i];
if ( i == mapsArray.length - 1 ) {
prevButton.disabled = false;
nextButton.disabled = true;
}
else if ( i == 0 ) {
prevButton.disabled = true;
nextButton.disabled = false;
}
else {
prevButton.disabled = false;
nextButton.disabled = false;
}
}
function nextBtn() {
if ( i < mapsArray.length - 1 ) {
i++;
}
update();
}
function prevBtn() {
if (i > 0) {
i--;
}
update();
}
update();
.maps{
display: flex;
justify-content: center;
align-items: center;
}
#myIframe {
width: 600px;
height: 600px;
}
<div class ="maps">
<iframe id='myIframe' class="maps-gallery active"></iframe>
</div>
<div class="btns">
<button id="prevBtn" onclick="prevBtn()" class="btn prev">Prev</button>
<button id="nextBtn" onclick="nextBtn()" class= "btn next" >Next</button>
</div>
Here is a minimalist solution to your problem. The short style probably is not everybody's but it shows how little you need to write to actually reproduce the logic.
The core of the random sequencing of array elements is the shuffling of the array according to Fisher-Yates. After that I simply step through the shuffled array and enable/disable the buttons accordingly.
function shuffle(a,n){ // shuffle array a in place (Fisher-Yates)
let m=a.length;
n=n||m-1;
for(let i=0,j;i<n;i++){
j=Math.floor(Math.random()*(m-i)+i);
if (j-i) [ a[i],a[j] ] = [ a[j],a[i] ]; // swap 2 array elements
}; return a
}
const mapsArray = shuffle([
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d209569.44700750793!2d-56.380275318336025!3d-34.84309361411796!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x959f802b6753b221%3A0x3257eb39860f05a6!2sPalacio%20Salvo!5e0!3m2!1sen!2suy!4v1614269355326!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d92110.09563909167!2d17.958933187703266!3d59.32686333113927!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x465f763119640bcb%3A0xa80d27d3679d7766!2sStockholm%2C%20Sweden!5e0!3m2!1sen!2suy!4v1614704350417!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d88989.45462143555!2d15.9390973!3d45.8128514!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4765d701f8ef1d1d%3A0x312b512f1e7f6df9!2sCathedral%20of%20Zagreb!5e0!3m2!1sen!2suy!4v1614704668458!5m2!1sen!2suy",
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d6709.917127499258!2d-78.51409209928569!3d0.3576385746900253!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8e2a5da2881 494ab%3A0xae89047fc027c897!2sapuela%20imbabura%20intac!5e0!3m2!1sen!2suy!4v1614704741586!5m2!1sen!2suy"]);
btns=document.querySelectorAll("button"), trgt=document.getElementById('myIframe');
trgt.src=mapsArray[0];
(i=>{
let n=mapsArray.length;
btns.forEach((b,k)=>b.onclick=()=>{
trgt.src=mapsArray[i=i+2*k-1];
btns[0].disabled=!i; btns[1].disabled=(i+1===n);
})
})(1); btns[0].click();
.maps {
display: flex;
justify-content: center;
align-items: center;
}
#myIframe {
width: 600px;
height: 600px;
}
<iframe id='myIframe' class="maps-gallery active"></iframe><br>
<button>Prev</button>
<button>Next</button>
The main function is embedded in an IIFE that encapsulates the current position index i and sets it to 0 as the starting value. The only "visible" global elements are the function shuffle() and the array mapsArray itself. For the actual stepping I apply a little trick: while in the .forEach() loop I use the index k to determine whether next(=1) or previous(=0) was clicked and then I calculate the increment accordingly.
I'm using fancybox to display image gallery.
I have this layout:
<div class="avatar">
<a class="avatar-item" data-fancybox="group" data-caption="Caption #1" href="img/avatars/jessica1.jpeg">
<img src="./img/avatars/jessica1.jpeg" width="145" height="145" alt="">
</a>
<a class="avatar-item" data-fancybox="group" data-caption="Caption #2" href="img/avatars/jessica2.jpeg">
<img src="./img/avatars/jessica2.jpeg" alt="">
</a>
</div>
And when I click on preview - gallery popup occurs, but it shows 4 images instead of 2. I included fancybox via data-attributes, without javascript. Tried magnific popup with gallery option - got same result.
link href attribute value and internal image src attribute are the same.
I don't have a thumbnail, display image cropped with css.
Hee is CSS:
.avatar {
&.slick-dotted.slick-slider {
margin-bottom: 0;
}
a.avatar-item {
width: 146px;
height: 146px;
display: inline-block;
}
width: 146px;
height: 146px;
border: 4px solid #FFF;
float: left;
position: relative;
overflow: hidden;
img {
height: 100%;
}
}
Found the problem. I use slick-slider before with infinite: true parameter, which creates an extra slides, so I got count slides x2
I have extended the _run function. Now duplicate images are removed from the gallery and still the correct key is returned. Furthermore I have the possibility to arrange the images in any order via data-facybox position.
So it is also possible to use the infinity version of the slick slider.
function _run(e, opts) {
var tempItems,
items = [],
newItem,
reOrder,
duplicates = false,
pos,
index = 0,
$target,
value,
instance;
// Avoid opening multiple times
if (e && e.isDefaultPrevented()) {
return;
}
e.preventDefault();
opts = opts || {};
if (e && e.data) {
opts = mergeOpts(e.data.options, opts);
}
$target = opts.$target || $(e.currentTarget).trigger("blur");
instance = $.fancybox.getInstance();
if (instance && instance.$trigger && instance.$trigger.is($target)) {
return;
}
if (opts.selector) {
tempItems = $(opts.selector);
} else {
// Get all related items and find index for clicked one
value = $target.attr("data-fancybox") || "";
if (value) {
tempItems = e.data ? e.data.items : [];
tempItems = tempItems.length ? tempItems.filter('[data-fancybox="' +
value + '"]') : $('[data-fancybox="' + value + '"]');
} else {
tempItems = [$target];
}
}
if (tempItems.length > 1) {
$.each(tempItems, function(key, item) { // prevents duplicate images in the gallery
newItem = false;
if (typeof item !== 'undefined') {
if (items.length > 0) {
var found = items.filter(function (items) { return items.href ==
item.href });
if (found.length == 0) {
newItem = true;
} else {
duplicates = true;
}
} else {
newItem = true;
}
}
if (newItem) {
// Sort if the attribute data-fancybox-pos exists
if ($(item).data('fancybox-pos')) {
reOrder = true;
pos = $(item).data('fancybox-pos') - 1;
if (pos in items) {
tempItem = items[pos];
items[pos] = item;
items.push(tempItem);
} else {
items[pos] = item;
}
} else {
items.push(item);
}
}
});
} else {
items = tempItems;
}
if (duplicates || reOrder) {
// find correct index if there were duplicates
$.each(items, function(key, item) {
if (item.href == $target[0].href) {
index = key;
}
});
} else {
index = $(items).index($target);
}
// Sometimes current item can not be found
if (index < 0) {
index = 0;
}
instance = $.fancybox.open(items, opts, index);
// Save last active element
instance.$trigger = $target;
}
I've made a JavaScript dropdown menu. Everything works fine, except the background image. I have the image set to change when the dropdown menu is expanded, which also works fine.
The issue is with the headers. Unless the header is set to display inline-block or inline, the menu won't expand. When set to inline-block or inline everything expands when you click on the box. But if you click on the header itself, it adds the padding and border around the header and ads in the background image from the div. How do you prevent this from happening?
<div class="panel">
<div class="collapse"><h2>Features</h2></div>
<div class="elements">
text<br>text<br>text
</div>
</div>
<style>
h2 {/*display: inline-block;*/
/*display: inline;*/
margin: 0px;
padding: 0px 0px 0px 0px;
color: #ffffff;
text-align: center;
text-transform: uppercase;}
.expand,
.collapse {cursor: pointer;
background-position: center right;
background-repeat: no-repeat;
background-color: #000033;
border: 2px solid #990044;
color: #ffffff;
padding: 10px 0px;
text-align: center;}
.collapse {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAABHUlEQVRIS+3USw6CMBAA0BYNutOjcAQ9iXHjhoXhBt4AEmwwbvQm6g04ii4hCLaNNRUp/dDgQllRPvMy05lC0PMFe/bAH7Re8R8qaYySTZGPoyBYXm3WMQwP04Gbhfd8FJDYtKTxNjkCCBf4Ni3y0dwWSrChm51wXI/FhjHaRXix5rKygtYwGr4C1QUitPdKUJ7xemILbcJw7JsDnBktqU20DfP9VfoaCxuoDCPJvc1hF1QF+wBNy6uKNYK6qA4mBFVRXawVlKHkPTfUbKJo65NuFJ1W0sNb1EjPgOQEUcakGbJIApRPQpoZ+1iaoQKqjCln2IJqYdpgrZGArEGaGke5pPzPZE/Juq0bjbtU9KPpc6MMTTGjPeyCfQV8AK4c2lwJRjQ3AAAAAElFTkSuQmCC);}
.expand {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAABD0lEQVRIS+3Wyw2CQBAG4F1Q8KadSAnYgR0YL164SCWYKDHxonZgB1ICdiI3QR6yCgSVXXaAkGDkwgXyZf6dYcCo5Qu37KFugIaxH5FkdH1+hSYErpBgPck9E8j35AkUBYE5TEkqs6EoN1iApWmCUC6QgYHRUpCCOYk0zDUNV6VMkIYJSFAJFKLQim8glAqyME1b2AQ0zZ0CRQtBHiyNEop+gRCsCvoGVsGgaAbWwSDoE2wC40VxkxgPiteb7QFhPMsNsEPmLG196DZgolF0fFXYd614M47jhxvBCtEIXfy7rGZnKEq3k4jEZd3KPhMhcxqgYBV4gylZZaXf0qqR0t77g00n2pG/tjpl/37TPACe/d8VUJ3+EgAAAABJRU5ErkJggg==);}
.elements {background-color: #ccd9ff;
overflow: hidden;}
</style>
<script>
function aaManageEvent (eventObj, event, eventHandler) {
if (eventObj.addEventListener) {eventObj.addEventListener (event, eventHandler, false);}
else if (eventObj.attachEvent) {event = "on" + event; eventObj.attachEvent (event, eventHandler);}
}
window.onload = function () {
var divs = document.getElementsByTagName ("div");
for (var i = 0; i < divs.length; i++) {
if (divs[i].className == "collapse") {
aaManageEvent (divs [i], "click", spring.expandOrCollapse);
}
else if (divs[i].className == "elements") {
var height = divs [i].offsetHeight;
divs [i] .height = height;
if (divs [i] .id == "") divs [i].id = "div" + i;
divs [i].style.height = "0";
}
}
}
var spring = {
// adjust height
adjustItem : function (val, newItem) {
document.getElementById (newItem).style.height = val + "px";
},
// check if expand or collapse
expandOrCollapse : function (evnt) {
evnt = evnt ? evnt : window.event;
var target = evnt.target ? evnt.target : evnt.srcElement;
if (target.className == "collapse") spring.expand (target);
else spring.collapse (target);
},
// Expand Panel
expand : function (target) {
target.className = 'expand';
var children = target.parentNode.childNodes, panel;
for (var i = 0; i < children.length; i++) {
if (children [i].className == "elements") {
panel = children [i]; break;
}
}
var height = panel.height, incr = height / 20;
for (var i=0; i < 20; i++) {
var val = (i + 1) * incr;
var func = "spring.adjustItem (" + val + ", '" + panel.id + "')";
setTimeout (func, (i + 1) * 30);
}
},
// Collapse Panel
collapse : function (target) {
target.className = "collapse";
var children = target.parentNode.childNodes, panel;
for (var i = 0; i < children.length; i++) {
if (children [i].className == "elements") {
panel = children [i]; break;
}
}
var height = panel.height, decr = height / 20;
for (var i = 0; i < 20; i++) {
var val = height - (decr * (i + 1));;
var func = "spring.adjustItem (" + val + ", '" + panel.id + "')";
setTimeout (func, (i + 1) * 30);
}
}
};
</script>
When I click on the div, the dropdown works. But when I click on the header, I see an error in the browser console.
I think because when clicking on the <h2>Features</h2> element, the click event bubbles up to the <div class="collapse">, making the var target in this line not the <div class="collapse"> but the <h2>:
var target = evnt.target ? evnt.target : evnt.srcElement;
A possible solution to fix this is for example to add an id to this line:
<div id="header" class="collapse"><h2>Features</h2></div>
Then you can directly get that div by id and change the classname.
I've adjusted your expandOrCollapse function to make it toggle based on the classname from the div with id="header".
For example:
function aaManageEvent (eventObj, event, eventHandler) {
if (eventObj.addEventListener) {eventObj.addEventListener (event, eventHandler, false);}
else if (eventObj.attachEvent) {event = "on" + event; eventObj.attachEvent (event, eventHandler);}
}
window.onload = function () {
var divs = document.getElementsByTagName ("div");
for (var i = 0; i < divs.length; i++) {
if (divs[i].className == "collapse") {
aaManageEvent (divs [i], "click", spring.expandOrCollapse);
}
else if (divs[i].className == "elements") {
var height = divs [i].offsetHeight;
divs [i] .height = height;
if (divs [i] .id == "") divs [i].id = "div" + i;
divs [i].style.height = "0";
}
}
}
var spring = {
// adjust height
adjustItem : function (val, newItem) {
document.getElementById (newItem).style.height = val + "px";
},
// check if expand or collapse
expandOrCollapse : function (evnt) {
var header = document.getElementById('header');
if (header.className === "collapse") {
spring.expand(header);
} else {
spring.collapse(header);
}
},
// Expand Panel
expand : function (target) {
target.className = 'expand';
var children = target.parentNode.childNodes, panel;
for (var i = 0; i < children.length; i++) {
if (children [i].className == "elements") {
panel = children [i]; break;
}
}
var height = panel.height, incr = height / 20;
for (var i=0; i < 20; i++) {
var val = (i + 1) * incr;
var func = "spring.adjustItem (" + val + ", '" + panel.id + "')";
setTimeout (func, (i + 1) * 30);
}
},
// Collapse Panel
collapse : function (target) {
target.className = "collapse";
var children = target.parentNode.childNodes, panel;
for (var i = 0; i < children.length; i++) {
if (children [i].className == "elements") {
panel = children [i]; break;
}
}
var height = panel.height, decr = height / 20;
for (var i = 0; i < 20; i++) {
var val = height - (decr * (i + 1));;
var func = "spring.adjustItem (" + val + ", '" + panel.id + "')";
setTimeout (func, (i + 1) * 30);
}
}
};
h2 {/*display: inline-block;*/
/*display: inline;*/
margin: 0px;
padding: 0px 0px 0px 0px;
color: #ffffff;
text-align: center;
text-transform: uppercase;}
.expand,
.collapse {cursor: pointer;
background-position: center right;
background-repeat: no-repeat;
background-color: #000033;
border: 2px solid #990044;
color: #ffffff;
padding: 10px 0px;
text-align: center;}
.collapse {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAABHUlEQVRIS+3USw6CMBAA0BYNutOjcAQ9iXHjhoXhBt4AEmwwbvQm6g04ii4hCLaNNRUp/dDgQllRPvMy05lC0PMFe/bAH7Re8R8qaYySTZGPoyBYXm3WMQwP04Gbhfd8FJDYtKTxNjkCCBf4Ni3y0dwWSrChm51wXI/FhjHaRXix5rKygtYwGr4C1QUitPdKUJ7xemILbcJw7JsDnBktqU20DfP9VfoaCxuoDCPJvc1hF1QF+wBNy6uKNYK6qA4mBFVRXawVlKHkPTfUbKJo65NuFJ1W0sNb1EjPgOQEUcakGbJIApRPQpoZ+1iaoQKqjCln2IJqYdpgrZGArEGaGke5pPzPZE/Juq0bjbtU9KPpc6MMTTGjPeyCfQV8AK4c2lwJRjQ3AAAAAElFTkSuQmCC);}
.expand {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAABD0lEQVRIS+3Wyw2CQBAG4F1Q8KadSAnYgR0YL164SCWYKDHxonZgB1ICdiI3QR6yCgSVXXaAkGDkwgXyZf6dYcCo5Qu37KFugIaxH5FkdH1+hSYErpBgPck9E8j35AkUBYE5TEkqs6EoN1iApWmCUC6QgYHRUpCCOYk0zDUNV6VMkIYJSFAJFKLQim8glAqyME1b2AQ0zZ0CRQtBHiyNEop+gRCsCvoGVsGgaAbWwSDoE2wC40VxkxgPiteb7QFhPMsNsEPmLG196DZgolF0fFXYd614M47jhxvBCtEIXfy7rGZnKEq3k4jEZd3KPhMhcxqgYBV4gylZZaXf0qqR0t77g00n2pG/tjpl/37TPACe/d8VUJ3+EgAAAABJRU5ErkJggg==);}
.elements {background-color: #ccd9ff;
overflow: hidden;}
<div class="panel">
<div id="header" class="collapse"><h2>Features</h2></div>
<div class="elements">
text<br>text<br>text
</div>
</div>
Edit your declaration block of h2 as shown below. This will solve your problem.
h2 {
display: inline-block;
margin: 0px;
padding: 0px 0px 0px 0px;
color: #ffffff;
text-align: center;
text-transform: uppercase;
pointer-events: none; // this line solves your problem.
}
CSS property pointer-events let you control under what circumstances an element can become the target of mouse events. when you set it to none, the element will never be the target of mouse events. So, the click event passed on to its descendant elements (here the box).
Using PhotoSwipe the thumbnail gallery markup looks like this:
<div class="wrap clearfix">
<div class="my-gallery" itemscope itemtype="http://schema.org/ImageGallery">
<ul class="gallery-grid">
<li>
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="img/dektop/1.jpg" itemprop="contentUrl" data-size="1200x1200">
<img src="img/thumb/1.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Image caption 1</figcaption>
</figure>
</li>
<li>
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="img/dektop/2.jpg" itemprop="contentUrl" data-size="1200x1200">
<img src="img/thumb/2.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Image caption 2</figcaption>
</figure>
</li>
</ul>
</div> <!-- mygallery -->
</div> <!-- wrap -->
The function to parse the images is:
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
size = linkEl.getAttribute('data-size').split('x');
// create slide object
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('src');
}
item.el = figureEl; // save link to element for getThumbBoundsFn
items.push(item);
}
return items;
};
I have two additional elements between the my-gallery and the figure class. Removing those things work perfect, however with the additional two classes I cannot select the previous or next item, meaning the array is broken.
How can I include the gallery-grid and li elements in the function so that is looks past those elements for figure and children.
Totally new to pure JS, any hints or further reading very welcome. Unfortunately with this one I have no clue where to even start looking.
http://quirksmode.org/dom/core/#gettingelements
https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName
I managed by leaving the original markup in place and change the CSS for the thumbnail gallery. It now works and looks like this:
<div class="wrap clearfix">
<div class="my-gallery gallery-grid" itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="img/dektop/1.jpg" itemprop="contentUrl" data-size="1200x1200">
<img src="img/thumb/1.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Image caption 4</figcaption>
</figure>
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="img/dektop/2.jpg" itemprop="contentUrl" data-size="1200x1200">
<img src="img/thumb/2.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Image caption 4</figcaption>
</figure>
</div> <!-- mygallery -->
</div> <!-- wrap -->
And the CSS for the the thumbnail grid:
/* thumnail gallery grid */
.gallery-grid {
margin: 35px 0 0 0;
padding: 0;
list-style: none;
position: relative;
width: 100%;
}
.gallery-grid figure {
position: relative;
float: left;
overflow: hidden;
width: 16.6666667%; /* Fallback */
width: -webkit-calc(100% / 6);
width: calc(100% / 6);
height: 300px; /* pay attention to this later */
}
.gallery-grid figure a,
.gallery-grid figure a img {
display: block;
width: 100%;
height: auto;
cursor: pointer;
}
.gallery-grid figure a img {
width: 100%;
height: auto;
}
#media screen and (max-width: 1190px) {
.gallery-grid figure {
width: 20%; /* Fallback */
width: -webkit-calc(100% / 5);
width: calc(100% / 5);
}
}
#media screen and (max-width: 945px) {
.gallery-grid figure {
width: 25%; /* Fallback */
width: -webkit-calc(100% / 4);
width: calc(100% / 4);
}
}
#media screen and (max-width: 660px) {
.gallery-grid figure {
width: 33.3333333%; /* Fallback */
width: -webkit-calc(100% / 3);
width: calc(100% / 3);
}
}
#media screen and (max-width: 660px) {
.gallery-grid figure {
width: 33.3333333%; /* Fallback */
width: -webkit-calc(100% / 3);
width: calc(100% / 3);
}
}
#media screen and (max-width: 400px) {
.gallery-grid figure {
width: 50%; /* Fallback */
width: -webkit-calc(100% / 2);
width: calc(100% / 2);
}
}
#media screen and (max-width: 300px) {
.gallery-grid figure {
width: 100%;
}
}
However this is not really an answer but a workaround to accommodate for the original markup. I would still very much love to find out about how to change the JS to work with the markup from my question.
I am using the example from here:
http://photoswipe.com/documentation/getting-started.html
At the bottom there is a CodePen.
Old question and we had little bit different markup, but if somebody is trying to figure this out like me this might work as it did to me:
https://github.com/akizor/PhotoSwipe-Gallery-Improvement
All you need to do is include Photoswipe library, add a HTML tag that acts as a container for all your gallery images and use this javascript in your page.
I used div with a class .images-container as a container.
var initPhotoSwipeFromDOM = function(gallerySelector) {
var parseThumbnailElements = function(el) {
var all = document.querySelectorAll(gallerySelector);
var items = [];
for(var j = 0 ; j < all.length; j++){
var el = all[j];
var thumbElements = el.parentNode.childNodes;
var numNodes = thumbElements.length,
figureEl,
linkEl,
size,
item;
for(var i = 0; i < numNodes; i++) {
figureEl = thumbElements[i];
if(figureEl.nodeType !== 1) {
continue;
}
linkEl = figureEl.children[0];
size = linkEl.getAttribute('data-size').split('x');
item = {
src: linkEl.getAttribute('href'),
w: parseInt(size[0], 10),
h: parseInt(size[1], 10),
minZoom: 3
};
if(figureEl.children.length > 1) {
item.title = figureEl.children[1].innerHTML;
}
if(linkEl.children.length > 0) {
item.msrc = linkEl.children[0].getAttribute('src');
}
item.el = figureEl;
items.push(item);
}
}
return items;
};
var closest = function closest(el, fn) {
return el && ( fn(el) ? el : closest(el.parentNode, fn) );
};
var onThumbnailsClick = function(e) {
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var eTarget = e.target || e.srcElement;
var clickedListItem = closest(eTarget, function(el) {
return (el.tagName && el.tagName.toUpperCase() === 'FIGURE');
});
if(!clickedListItem) {
return;
}
var clickedGallery = clickedListItem.parentNode,
childNodes = document.querySelectorAll(gallerySelector),
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) {
openPhotoSwipe( index, clickedGallery );
}
return false;
};
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);
options = {
maxSpreadZoom: 5,
galleryUID: galleryElement.getAttribute('data-pswp-uid'),
getThumbBoundsFn: function(index) {
var thumbnail = items[index].el.getElementsByTagName('img')[0],
pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
rect = thumbnail.getBoundingClientRect();
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
},
minZoom: 3
};
if(fromURL) {
if(options.galleryPIDs) {
for(var j = 0; j < items.length; j++) {
if(items[j].pid == index) {
options.index = j;
break;
}
}
} else {
options.index = parseInt(index, 10) - 1;
}
} else {
options.index = parseInt(index, 10);
}
if( isNaN(options.index) ) {
return;
}
if(disableAnimation) {
options.showAnimationDuration = 0;
}
gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
return gallery.init();
};
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;
}
var hashData = photoswipeParseHash();
if(hashData.pid && hashData.gid) {
openPhotoSwipe( hashData.pid , galleryElements[ hashData.gid - 1 ], true, true );
}
};
// execute above function
initPhotoSwipeFromDOM('.images-container figure');