<section class="media media--grid">
<div class="media__in">
<div class="media__inner">
<div class="media__content">
<div class="media__item">
<div class="media__item__inner">
<picture class="visual">
<source media="(max-width: 899px)" data-sizes="auto" data-srcset="/graphics/video-poster-mobile.webp" type="image/webp">
<source media="(max-width: 899px)" data-sizes="auto" data-srcset="/graphics/video-poster-mobile.jpg">
<source media="(min-width: 900px)" data-sizes="auto" data-srcset="/graphics/video-poster.webp" type="image/webp">
<source media="(min-width: 900px)" data-sizes="auto" data-srcset="/graphics/video-poster.jpg">
<img data-sizes="auto" data-src="/graphics/video-poster-mobile.jpg" class="lazyload" alt="">
</picture>
</div>
</div>
<div class="media__item">
<div class="media__item__inner">
<picture class="visual">
<source media="(max-width: 899px)" data-sizes="auto" data-srcset="/graphics/video-poster-mobile.webp" type="image/webp">
<source media="(max-width: 899px)" data-sizes="auto" data-srcset="/graphics/video-poster-mobile.jpg">
<source media="(min-width: 900px)" data-sizes="auto" data-srcset="/graphics/video-poster.webp" type="image/webp">
<source media="(min-width: 900px)" data-sizes="auto" data-srcset="/graphics/video-poster.jpg">
<img data-sizes="auto" data-src="/graphics/video-poster-mobile.jpg" class="lazyload" alt="">
</picture>
</div>
</div>
<div class="media__item">
<div class="media__item__inner">
<picture class="visual">
<source media="(max-width: 899px)" data-sizes="auto" data-srcset="/graphics/video-poster-mobile.webp" type="image/webp">
<source media="(max-width: 899px)" data-sizes="auto" data-srcset="/graphics/video-poster-mobile.jpg">
<source media="(min-width: 900px)" data-sizes="auto" data-srcset="/graphics/video-poster.webp" type="image/webp">
<source media="(min-width: 900px)" data-sizes="auto" data-srcset="/graphics/video-poster.jpg">
<img data-sizes="auto" data-src="/graphics/video-poster-mobile.jpg" class="lazyload" alt="">
</picture>
</div>
</div>
<div class="media__item">
<div class="media__item__inner">
<picture class="visual">
<source media="(max-width: 899px)" data-sizes="auto" data-srcset="/graphics/video-poster-mobile.webp" type="image/webp">
<source media="(max-width: 899px)" data-sizes="auto" data-srcset="/graphics/video-poster-mobile.jpg">
<source media="(min-width: 900px)" data-sizes="auto" data-srcset="/graphics/video-poster.webp" type="image/webp">
<source media="(min-width: 900px)" data-sizes="auto" data-srcset="/graphics/video-poster.jpg">
<img data-sizes="auto" data-src="/graphics/video-poster-mobile.jpg" class="lazyload" alt="">
</picture>
</div>
</div>
</div>
</div>
<div class="media__loadmore">
<a href="/media/data.json?page=" class="loadmore">
<span class="loadmore__icon">
<span class="icon-plus">
<span class="icon-plus__inner"></span>
</span>
</span>
<span class="loadmore__label">load more media</span>
</a>
</div>
</div>
</section>
<section class="media media--grid">
<div class="media__in">
<div class="media__inner">
<div class="media__content">
<div class="media__item">
<div class="media__item__inner">
{{render '@visual' }}
</div>
</div>
<div class="media__item">
<div class="media__item__inner">
{{render '@visual' }}
</div>
</div>
<div class="media__item">
<div class="media__item__inner">
{{render '@visual' }}
</div>
</div>
<div class="media__item">
<div class="media__item__inner">
{{render '@visual' }}
</div>
</div>
</div>
</div>
<div class="media__loadmore">
{{render '@loadmore' }}
</div>
</div>
</section>
type: grid
variant: A
content:
modifier: right
{
"mediaitems": [
{
"image": "/graphics/video-player.jpg",
"video-src": "",
"type": "image",
"item-id": "{04a25187-d2b0-4b65-937d-80aeedc98ac2}",
"total-records": "100"
},
{
"image": "/graphics/video-player.jpg",
"video-src": "",
"type": "image",
"item-id": "{04a25187-d2b0-4b65-937d-80aeedc98ac2}",
"total-records": "100"
},
{
"image": "/graphics/video-player.jpg",
"video-src": "",
"type": "image",
"item": "{04a25187-d2b0-4b65-937d-80aeedc98ac2}",
"total-records": "100"
},
{
"image": "/graphics/video-player.jpg",
"video-src": "",
"type": "image",
"item-id": "{04a25187-d2b0-4b65-937d-80aeedc98ac2}",
"total-records": "100"
}
]
}
const MEDIA = ((w, d, undefined) => {
'use strict';
const selectors = {
theWrap: '.media--grid',
theTrigger: '.loadmore',
theContent: '.media__content',
theItem: '.media__item',
};
const classes = {
mediaItem: 'media__item',
inView: 'in-view',
isLoading: 'is-loading',
allLoaded: 'all-loaded',
};
const els = {};
const api = {
url: '',
method: 'GET',
};
const paging = {
page: 1,
step: 4,
max: 0,
};
const animateItems = [];
let anchor = null;
let appendTimer = null;
let animateTimer = null;
const init = () => {
els.theWraps = d.querySelectorAll(selectors.theWrap);
if (els.theWraps.length <= 0) { return; }
bindIt();
};
const bindIt = () => {
[...els.theWraps].forEach((theWrap) => {
const theTrigger = theWrap.querySelector(selectors.theTrigger);
const theItems = theWrap.querySelectorAll(selectors.theItem);
if (theTrigger) {
api.url = theTrigger.href;
theTrigger.addEventListener('click', (e) => {
e.preventDefault();
loadmore(theWrap);
});
loadmore(theWrap, true);
}
observeIt([...theItems]);
});
};
const observeIt = (theItems) => {
theItems.forEach((theItem) => {
const observer = new IntersectionObserver((item) => {
if (item[0].isIntersecting) {
animateItems.push(theItem);
animateIt();
observer.unobserve(theItem);
}
}, {
rootMargin: `-20% 0px -20%`,
treshold: thresholdArray(20),
});
observer.observe(theItem);
});
};
const loadmore = (theWrap, onInit) => {
if (!theWrap) { return; }
const theContent = theWrap.querySelector(selectors.theContent);
if (!theContent) { return; }
!onInit && theWrap.classList.add(classes.isLoading);
fetchIt(theWrap, theContent, buildIt, onInit);
};
const fetchIt = (theWrap, theContent, cb, onInit) => {
const req = new XMLHttpRequest();
req.open(api.method, api.url + paging.page);
req.send();
req.onreadystatechange = () => {
if (req.readyState === XMLHttpRequest.DONE) {
theWrap.classList.remove(classes.isLoading);
if (req.status === 200) {
const result = isJSON(req.responseText) ? JSON.parse(req.responseText) : false;
if (!result) {
theWrap.classList.add(classes.allLoaded);
return;
}
const theItems = result ? result['mediaitems'] : [];
paging.max = !theItems.length ? null : theItems[0]['total-records'];
if (!paging.max) {
theWrap.classList.add(classes.allLoaded);
return;
}
if (onInit) { return; }
cb(theContent, theItems);
paging.page++;
paging.page * paging.step >= parseInt(paging.max, 10) && theWrap.classList.add(classes.allLoaded);
} else {
theWrap.classList.add(classes.isLoading);
console.log('There was a problem with the request.');
}
}
};
};
const buildIt = (theContent, theItems) => {
if (!theContent || !theItems.length) { return; }
const newItems = [];
theItems.forEach((theItem) => {
const mediaItem = getHTML(theItem);
newItems.push(mediaItem);
});
anchor = newItems[0];
appendIt(theContent, newItems, 0);
observeIt(newItems);
};
const getHTML = (theItem) => {
let html = '';
const mediaItem = d.createElement('div');
mediaItem.classList.add(classes.mediaItem);
if (theItem.type === 'image') {
html = `
<div class="media__item__inner">
<picture class="visual">
<img src="${theItem['image']}" alt="">
</picture>
</div>
`;
}
if (theItem.type === 'video-bg') {
html = `
<div class="media__item__inner">
<div class="video-bg">
<video loop="" muted="" playsinline="" poster="${theItem['image']}" src="${theItem['video-src']}"></video>
<a class="video-bg__control video-bg__control--right">
<span class="icon-media">
<span class="icon-media__inner">
<span class="icon-media__pause">
<svg class="icon-media__play" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 7.6 14">
<path fill="currentColor" d="M7.4,6.3l-5.6-6c-0.4-0.4-1-0.4-1.4,0C0.1,0.5,0,0.7,0,1v12c0,0.6,0.4,1,1,1c0.3,0,0.5-0.1,0.7-0.3l5.6-6C7.7,7.3,7.7,6.7,7.4,6.3z"></path>
</svg>
</span>
</span>
</span>
</a>
</div>
</div>
`;
}
if (theItem.type === 'video-player') {
html = `
<div class="media__item__inner">
<div class="video-player">
<picture class="visual">
<img src="${theItem['image']}" alt="">
</picture>
<a class="video-player__trigger">
<span class="video-ID">${theItem['video-src']}</span>
<span class="icon-play">
<span class="icon-play__inner"></span>
<span class="icon-play__icon">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 7.6 14">
<path fill="currentColor" d="M7.4,6.3l-5.6-6c-0.4-0.4-1-0.4-1.4,0C0.1,0.5,0,0.7,0,1v12c0,0.6,0.4,1,1,1c0.3,0,0.5-0.1,0.7-0.3l5.6-6C7.7,7.3,7.7,6.7,7.4,6.3z"></path>
</svg>
</span>
</span>
</a>
</div>
</div>
`;
}
mediaItem.innerHTML = html;
return mediaItem;
};
const appendIt = (theContent, newItems, delay = 0) => {
clearTimeout(appendTimer);
appendTimer = setTimeout(() => {
theContent.appendChild(newItems[0]);
newItems[0].querySelector('.video-bg') && VIDEOBG.init();
newItems[0].querySelector('.video-player') && VIDEOOVERLAY.init();
newItems.shift();
newItems.length ? appendIt(theContent, newItems, 0) : scrollIt();
}, delay);
};
const scrollIt = () => {
if (!anchor) { return; }
anchor.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
};
const animateIt = (delay = 100) => {
clearTimeout(animateTimer);
animateTimer = setTimeout(() => {
animateItems[0].classList.add(classes.inView);
animateItems.shift();
animateItems.length && animateIt(100);
}, delay);
};
const isJSON = (theString) => {
if (!theString) { return false; }
try {
JSON.parse(theString);
} catch (e) {
return false;
}
return true;
};
const thresholdArray = steps => Array(steps + 1).fill(0).map((_, index) => index / steps || 0);
d.addEventListener('DOMContentLoaded', init);
})(window, window.document);
.media {
display: block;
width: 100%;
padding: 0 var(--gutter--bucket);
&.media--slider {
padding: 0;
}
}
.media__in {
position: relative;
max-width: var(--section--9);
margin: 0 auto;
.media--contained &,
.media--grid & {
max-width: var(--section--8);
margin: 0 auto;
}
}
.media__inner {
position: relative;
width: 100%;
.media--full &,
.media--contained & {
display: block;
height: 0;
padding-top: (206 / 352) * 100%;
}
.media--full & {
@media (min-width: 900px) {
padding-top: (650 / 1420) * 100%;
}
}
.media--contained & {
@media (min-width: 900px) {
padding-top: (650 / 1110) * 100%;
}
}
.media--grid & {
overflow: hidden;
}
}
.media__header {
position: absolute;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
padding: var(--gutter--bucket);
}
.media__heading {
flex: 0 1 var(--section--6);
color: var(--color--neutrals-0);
font-weight: 500;
text-align: center;
}
.media__content {
.media--grid & {
display: flex;
flex-wrap: wrap;
margin: -2px;
}
}
.media__item {
position: relative;
flex: 0 0 100%;
padding: 2px;
@media (min-width: 500px) {
flex: 0 0 50%;
}
}
.media__item:before {
.media:not(.media--grid):not(.media--grid-b) & {
position: absolute;
top: 2px;
right: 2px;
bottom: 2px;
left: 2px;
z-index: 1;
display: block;
background-color: var(--color--neutrals-1);
content: '';
}
}
.media__item__inner {
position: relative;
z-index: 2;
display: block;
width: 100%;
height: 0;
padding-top: 100%;
overflow: hidden;
background-color: var(--color--neutrals-1);
opacity: 0;
.media--grid & {
padding-top: (9 / 16) * 100%;
}
.in-view & {
transition: opacity 750ms;
opacity: 1;
}
}
.media__loadmore {
margin-top: var(--gap--2);
@media (min-width: 750px) {
margin-top: var(--gap--4);
}
.all-loaded & {
display: none;
}
}
.media__slider {
height: 0;
overflow: hidden;
&.swiper-container-initialized {
height: auto;
}
}
.media__slide {
position: relative;
display: block;
width: 100%;
height: 0;
padding-top: 80% !important;
//padding-top: (427 / 375) * 100%;
@media (min-width: 750px) {
padding-top: (650 / 885) * 100% !important;
}
}
.media__thumbs {
margin-top: var(--gap--1);
padding-bottom: var(--gap--2);
@media (min-width: 900px) {
margin-top: var(--gap--2);
}
}
.media__thumb {
transition: opacity 250ms;
position: relative;
display: block;
width: 100%;
height: 0;
padding-top: (650 / 885) * 100%;
opacity: .7;
cursor: pointer;
&:hover {
opacity: 1;
}
.swiper-slide-thumb-active & {
opacity: 1;
}
&:after {
transition: height 250ms;
position: absolute;
bottom: 0;
left: 0;
display: block;
width: 100%;
height: 0;
margin-bottom: calc(var(--gap--2) * -1);
background-color: var(--color--action);
content: '';
}
.swiper-slide-thumb-active &:after {
height: 4px;
}
}
.media__nav {
transition: opacity 300ms;
transform: translate(-50%, -50%);
position: absolute;
top: 50%;
left: 50%;
z-index: 4;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
// max-width: var(--section--8);
opacity: 1;
pointer-events: none;
@media (min-width: 900px) {
padding: 0 var(--gutter--bucket);
}
.swiper-slide:not(.swiper-slide-active) & {
display: none;
}
}
.media__nav__item {
flex: none;
display: flex;
justify-content: center;
width: calc(var(--gutter--bucket) * 3);
}
.media__nav__link {
transition: opacity 250ms;
position: relative;
flex: none;
display: flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
color: var(--color--action);
border-radius: 50%;
pointer-events: all;
opacity: 1;
@media (min-width: 900px) {
width: 40px;
height: 40px;
}
&:hover {
color: var(--color--action);
text-decoration: none;
cursor: pointer;
}
&[aria-disabled="true"] {
pointer-events: none;
opacity: 0;
}
}
.media__nav__link:before {
transition: box-shadow 250ms, opacity 250ms;
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: var(--color--neutrals-0);
box-shadow: 0 2px 4px rgba(#000, .14);
opacity: .8;
}
.media__nav__link:hover:before {
opacity: 1;
box-shadow: 0 4px 4px rgba(#000, .14);
}
.media__nav__link:active:before {
box-shadow: 0 0 5px rgba(#000, .14);
}
.media__nav__icon {
position: relative;
flex: none;
width: 44%;
.media__nav__link--prev & {
transform: translate(-1px, 0) rotate(180deg);
}
.media__nav__link--next & {
transform: translate(1px, 0);
}
}
No notes defined.