Skip to content
Snippets Groups Projects
Commit 83cf2d2f authored by Nico Graebling's avatar Nico Graebling
Browse files

Add support for image carousels

parent 6d3db94e
No related branches found
No related tags found
No related merge requests found
......@@ -49,5 +49,10 @@
{{ block "main" . }}{{ end }}
</main>
{{ block "footer" . }}{{ partialCached "site-footer.html" . }}{{ end }}
</body>
<script type="text/javascript" src="/js/carousel.js"></script>
<link rel="stylesheet" href="/css/carousel.css">
</body>
</html>
{{ .context.Scratch.Set "height" .height }}
{{ .context.Scratch.Set "unit" .unit }}
{{ .context.Scratch.Set "items" .items }}
{{ .context.Scratch.Set "source" .source }}
{{ $data := index .context.Site.Data.carouselImages .source }}
<div style="width:90%;" id="carousel10" class="carousel" duration="{{ .duration }}" items="{{ .items }}">
<ul>
{{ range $index, $slide := $data.images }}
<li id="c10_slide{{ add $index 1}}" style="min-width: calc(100%/{{ $.context.Scratch.Get "items" }}); padding-bottom: {{ $.context.Scratch.Get "height" }}{{ $.context.Scratch.Get "unit" }};"><img src="{{ $slide.image }}" alt="" /><div><div>{{ $slide.content_html }}</div></div></li>
{{ end }}
</ul>
{{ if not (eq ($data.images | len) 1 ) }}
<ol>
{{ range $index, $page := $data.images }}
<li><a href="#c10_slide{{ add $index 1 }}"></a></li>
{{ end }}
</ol>
<div class="prev">&lsaquo;</div>
<div class="next">&rsaquo;</div>
{{ end }}
</div>
.carousel {position: relative;}
.carousel ul {overflow: auto; display: flex; flex-wrap: nowrap; scroll-snap-type: x mandatory; scroll-snap-points-y: repeat(100%); scroll-behavior: smooth; background: gray; -ms-overflow-style: none; scrollbar-width: none; margin: 0; padding: 0;}
.carousel ul::-webkit-scrollbar {display: none; /* Hide scrollbar for Chrome, Safari and Opera */}
.carousel ul li {position: relative; min-width: 100%; list-style: none; background: url() center center / cover no-repeat; scroll-snap-align: start;}
.carousel ul li > * {position: absolute; left: 0; top: 0; width: 100%; height: 100%; }
.carousel ul li > img {object-fit: cover;}
.carousel ul li > div {display: flex; justify-content: center; align-items: center; color: white; font-weight: bold; font-size: 20px;}
.carousel ol {position: absolute; bottom: 15px; display: flex; justify-content: center; left: 50%; transform: translateX(-50%); z-index: 9;}
.carousel ol li {list-style: none; padding: 0 5px;}
.carousel ol li a {display: block; height: 10px; width: 10px; border: 2px solid white; background: transparent; border-radius: 100%;}
.carousel ol li.selected a {background: white;}
.carousel .prev, .carousel .next {display: none; user-select:none; cursor: pointer; font-size: 50px; color: white; position: absolute; left: 0; padding: 15px 15px 30px; top: 50%; transform: translateY(-50%); z-index: 9; line-height: 0;}
.carousel .next {left: auto; right: 0;}
\ No newline at end of file
document.addEventListener('DOMContentLoaded', function() {
const carousels = document.querySelectorAll('.carousel');
carousels.forEach(function( carousel ) {
const ele = carousel.querySelector('ul');
const amountvisible = Math.round(ele.offsetWidth/ele.querySelector('li:nth-child(1)').offsetWidth);
const bullets = carousel.querySelectorAll('ol li');
const slides = carousel.querySelectorAll('ul li');
const nextarrow = carousel.querySelector('.next');
const prevarrow = carousel.querySelector('.prev');
// Initialize the carousel
nextarrow.style.display = 'block';
prevarrow.style.display = 'block';
ele.scrollLeft = 0;
bullets[0].classList.add('selected');
slides[0].classList.add('selected');
if(amountvisible>1) {
var removeels = carousel.querySelectorAll('ol li:nth-last-child(-n + '+(amountvisible-1)+')');
removeels.forEach(function(removeel) {
removeel.remove();
});
}
const setSelected = function() {
bullets.forEach(function(bullet) {
bullet.classList.remove('selected');
});
slides.forEach(function(slide) {
slide.classList.remove('selected');
});
const scrolllength = carousel.querySelector('ul li:nth-child(2)').offsetLeft - carousel.querySelector('ul li:nth-child(1)').offsetLeft;
const nthchild = (Math.round((ele.scrollLeft/scrolllength)+1));
carousel.querySelector('ol li:nth-child('+nthchild+')').classList.add('selected');
carousel.querySelector('ul li:nth-child('+nthchild+')').classList.add('selected');
if(carousel.parentElement.parentElement.querySelector('.dynamictitle')) {
const title = carousel.querySelector('ul li:nth-child('+nthchild+') img').getAttribute('title');
if(title) carousel.parentElement.parentElement.querySelector('.dynamictitle').innerHTML = title;
}
}
const scrollTo = function(event) {
event.preventDefault();
ele.scrollLeft = ele.querySelector(this.getAttribute('href')).offsetLeft;
}
const nextSlide = function() {
if(!carousel.querySelector('ol li:last-child').classList.contains('selected')) {
carousel.querySelector('ol li.selected').nextElementSibling.querySelector('a').click();
} else {
carousel.querySelector('ol li:first-child a').click();
}
}
const prevSlide = function() {
if(!carousel.querySelector('ol li:first-child').classList.contains('selected')) {
carousel.querySelector('ol li.selected').previousElementSibling.querySelector('a').click();
} else {
carousel.querySelector('ol li:last-child a').click();
}
}
const setInteracted = function() {
ele.classList.add('interacted');
}
// Attach the handlers
ele.addEventListener("scroll", debounce(setSelected));
ele.addEventListener("touchstart", setInteracted);
ele.addEventListener('keydown', function (e){
if(e.key == 'ArrowLeft') ele.classList.add('interacted');
if(e.key == 'ArrowRight') ele.classList.add('interacted');
});
nextarrow.addEventListener("click", nextSlide);
nextarrow.addEventListener("mousedown", setInteracted);
nextarrow.addEventListener("touchstart", setInteracted);
prevarrow.addEventListener("click", prevSlide);
prevarrow.addEventListener("mousedown", setInteracted);
prevarrow.addEventListener("touchstart", setInteracted);
bullets.forEach(function(bullet) {
bullet.querySelector('a').addEventListener('click', scrollTo);
bullet.addEventListener("mousedown", setInteracted);
bullet.addEventListener("touchstart", setInteracted);
});
//setInterval for autoplay
if(carousel.getAttribute('duration')) {
setInterval(function(){
if (ele != document.querySelector(".carousel:hover ul") && ele.classList.contains('interacted')==false) {
nextarrow.click();
}
}, carousel.getAttribute('duration'));
}
}); //end foreach
}); //end onload
/**
* Debounce functions for better performance
* (c) 2021 Chris Ferdinandi, MIT License, https://gomakethings.com
* @param {Function} fn The function to debounce
*/
function debounce (fn) {
// Setup a timer
let timeout;
// Return a function to run debounced
return function () {
// Setup the arguments
let context = this;
let args = arguments;
// If there's a timer, cancel it
if (timeout) {
window.cancelAnimationFrame(timeout);
}
// Setup the new requestAnimationFrame()
timeout = window.requestAnimationFrame(function () {
fn.apply(context, args);
});
};
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment