feat(MediaModal): add navigation between medias

This commit is contained in:
Matthieu Bessat 2020-08-19 11:50:53 +02:00
parent a8bed7c7de
commit d29d1a0212
3 changed files with 152 additions and 45 deletions

View file

@ -49,8 +49,6 @@ if (description !== null) {
/** /**
* Gallery modal to view media in large * Gallery modal to view media in large
*/ */
let mediaModal = document.querySelector('#media-modal')
let mediaModalContent = document.querySelector('#media-modal-content')
// let mediaModalImage = document.querySelector('#media-modal img') // let mediaModalImage = document.querySelector('#media-modal img')
// let mediaModalVideo = document.querySelector('#media-modal video') // let mediaModalVideo = document.querySelector('#media-modal video')
// let mediaModalSource = document.querySelector('#media-modal video source') // let mediaModalSource = document.querySelector('#media-modal video source')
@ -66,26 +64,72 @@ let mediaModalContent = document.querySelector('#media-modal-content')
// }; // };
// } // }
// function enableScroll() { // function enableScroll() {
// window.onscroll = function() {}; // window.onscroll = function() {};
// } // }
let mediaModal = document.querySelector('#media-modal')
let mediaModalContent = document.querySelector('#media-modal-content')
let navLeft = document.getElementById('media-nav-left')
let navRight = document.getElementById('media-nav-right')
let currentMedia = {}
let mediaData = []
let openModal = (url, isVideo) => { let loadMedias = () => {
let list = document.querySelectorAll('.media-container')
//console.log(list)
list.forEach(m => {
mediaData.push({
isVideo: m.getAttribute('data-video') == 'true',
location: m.getAttribute('data-location')
})
})
}
loadMedias()
let openModal = (index) => {
mediaModal.style.visibility = 'visible' mediaModal.style.visibility = 'visible'
mediaModal.style.opacity = 1 mediaModal.style.opacity = 1
mediaModalContent.innerHTML = ""
currentMedia = mediaData[index]
fillModal(currentMedia)
//document.body.style.height = '100vh'
document.body.style.overflow = 'hidden'
document.body.style.userSelect = 'none'
document.body.style.touchAction = 'none'
setTimeout(() => {
const outsideClickListener = event => {
if (
!mediaModalContent.contains(event.target) && isVisible(mediaModalContent) &&
navLeft.querySelector(':hover') === null &&
navRight.querySelector(':hover') === null
) {
closeModal()
document.removeEventListener('click', outsideClickListener)
}
}
document.addEventListener('click', outsideClickListener)
}, 100)
}
const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length )
let fillModal = () => {
console.log(currentMedia)
mediaModalContent.innerHTML = ""
let attr = document.createAttribute('src') let attr = document.createAttribute('src')
attr.value = url attr.value = currentMedia.location
let el = null let el = null
if (isVideo) { if (currentMedia.isVideo) {
el = document.createElement('video') el = document.createElement('video')
el.setAttribute('controls', '') el.setAttribute('controls', '')
el.setAttribute('autoplay', '') el.setAttribute('autoplay', '')
el.setAttribute('name', 'media') el.setAttribute('name', 'media')
let source = document.createElement('source') let source = document.createElement('source')
source.setAttribute('src', url) source.setAttribute('src', currentMedia.location)
source.setAttribute('type', 'video/mp4') source.setAttribute('type', 'video/mp4')
el.appendChild(source) el.appendChild(source)
} else { } else {
@ -93,42 +137,48 @@ let openModal = (url, isVideo) => {
el.attributes.setNamedItem(attr) el.attributes.setNamedItem(attr)
} }
mediaModalContent.appendChild(el) mediaModalContent.appendChild(el)
//document.body.style.height = '100vh'
document.body.style.overflow = 'hidden'
document.body.style.touchAction = 'none'
setTimeout(() => { if (mediaData.indexOf(currentMedia) === 0) {
navLeft.className += ' disabled'
} else {
navLeft.className = navLeft.className.replace('disabled', '')
}
const outsideClickListener = event => { if (mediaData.indexOf(currentMedia) + 1 === mediaData.length) {
if (!mediaModalContent.contains(event.target) && isVisible(mediaModalContent)) { navRight.className += ' disabled'
closeModal() } else {
document.removeEventListener('click', outsideClickListener) navRight.className = navRight.className.replace('disabled', '')
} }
}
document.addEventListener('click', outsideClickListener)
}, 100)
} }
const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length )
let closeModal = () => { let closeModal = () => {
mediaModal.style.visibility = 'hidden' mediaModal.style.visibility = 'hidden'
mediaModal.style.opacity = 0 mediaModal.style.opacity = 0
document.body.style.overflow = 'initial' document.body.style.overflow = 'initial'
document.body.style.height = 'initial' document.body.style.height = 'initial'
document.body.style.touchAction = 'initial' document.body.style.touchAction = 'initial'
document.body.style.userSelect = 'initial'
let video = document.querySelector('#media-modal video') let video = document.querySelector('#media-modal video')
if (video !== null) { if (video !== null) {
video.pause() video.pause()
} }
} }
navLeft.onclick = () => {
if (mediaData.indexOf(currentMedia) === 0) { return; }
currentMedia = mediaData[mediaData.indexOf(currentMedia) - 1]
fillModal()
}
navRight.onclick = () => {
if (mediaData.indexOf(currentMedia) + 1 === mediaData.length) { return; }
currentMedia = mediaData[mediaData.indexOf(currentMedia) + 1]
fillModal()
}
/** /**
* Decode things * Decode things
*/ */
let formatPhone = (phone) => { let formatPhone = (phone) => {
if (phone.indexOf('+33') === 0) { if (phone.indexOf('+33') === 0) {
phone = '0' + phone.substr(3) phone = '0' + phone.substr(3)

View file

@ -275,6 +275,49 @@
opacity: 1; opacity: 1;
} }
.media-nav {
position: absolute;
width: .5em;
color: white;
opacity: 0.8;
cursor: pointer;
font-size: 1.25em;
transition: 0.2s all;
z-index: 9999;
width: 5em;
}
.media-nav.disabled {
opacity: 0.25 !important;
cursor: auto;
}
.media-nav-btn svg {
height: 2em;
filter: drop-shadow(2px 4px 6px black);
}
.media-nav-btn {
padding: 2em;
display: flex;
justify-content: center;
align-items: center;
}
.media-nav:hover {
opacity: 1;
transition: 0.2s all;
}
.media-nav-left {
left: 2em !important;
}
.media-nav-right {
right: 2em !important;
}
/* ***************************************************************************** /* *****************************************************************************
* SECTION * SECTION
@ -764,6 +807,17 @@ RESPONSIVE
height: 33em; height: 33em;
} }
/**
* MODAL
**/
.media-nav {
bottom: 0em;
}
.media-nav-btn {
padding-top: 1em;
padding-bottom: 1em;
}
/** /**
* MOSAIC CASES * MOSAIC CASES
*/ */

View file

@ -48,7 +48,11 @@
{% if data.gallery|length > 0 %} {% if data.gallery|length > 0 %}
<div class="media-mosaic mosaic-{{ data.gallery|length }}"> <div class="media-mosaic mosaic-{{ data.gallery|length }}">
{% for media in data.gallery %} {% for media in data.gallery %}
<div class="media-container" onclick="openModal('{{ media.location }}', {{ media.isVideo }})"> <div
class="media-container"
data-video="{{ media.isVideo }}"
data-location="{{ media.location }}"
onclick="openModal({{ loop.index - 1 }})">
<div <div
class="media {% if media.isVideo %}media-video-bg{% endif %}" class="media {% if media.isVideo %}media-video-bg{% endif %}"
{% if not media.isVideo %}style="background-image: url({{ media.location }})"{% endif %}></div> {% if not media.isVideo %}style="background-image: url({{ media.location }})"{% endif %}></div>
@ -65,7 +69,6 @@
<div class="media-modal-container" id="media-modal"> <div class="media-modal-container" id="media-modal">
<div class="media-modal"> <div class="media-modal">
<div class="media-modal-content" id="media-modal-content"> <div class="media-modal-content" id="media-modal-content">
</div> </div>
<div class="media-close" onclick="closeModal()"> <div class="media-close" onclick="closeModal()">
<svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> <svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
@ -73,6 +76,21 @@
</svg> </svg>
</div> </div>
</div> </div>
<div
id="media-nav-left"
class="media-nav-left media-nav">
<div class="media-nav-btn">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-left" class="svg-inline--fa fa-chevron-left fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z"></path></svg>
</div>
</div>
<div
id="media-nav-right"
class="media-nav-right media-nav">
<div class="media-nav-btn">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="chevron-right" class="svg-inline--fa fa-chevron-right fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"></path></svg>
</div>
</div>
</div> </div>
{% endif %} {% endif %}
@ -326,7 +344,7 @@
</div> </div>
<div class="contact-content"> <div class="contact-content">
<a href="{{ data.contacts.website|e }}"> <a href="{{ data.contacts.website|e }}">
{{ data.contacts.websiteLabel|e }} Site Web
<svg class="external-link" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> <svg class="external-link" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512">
<path fill="currentColor" d="M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z"></path> <path fill="currentColor" d="M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z"></path>
</svg> </svg>
@ -343,12 +361,7 @@
</div> </div>
<div class="contact-content"> <div class="contact-content">
<a href="{{ data.contacts.facebook|e }}"> <a href="{{ data.contacts.facebook|e }}">
<span class="short"> Page Facebook
{{ data.contacts.facebookLabel|e }}
</span>
<span class="long">
{{ data.contacts.facebook|e }}
</span>
<svg class="external-link" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> <svg class="external-link" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512">
<path fill="currentColor" d="M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z"></path> <path fill="currentColor" d="M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z"></path>
</svg> </svg>
@ -365,12 +378,7 @@
</div> </div>
<div class="contact-content"> <div class="contact-content">
<a href="{{ data.contacts.instagram|e }}"> <a href="{{ data.contacts.instagram|e }}">
<span class="short"> Profil Instagram
{{ data.contacts.instagramLabel|e }}
</span>
<span class="long">
{{ data.contacts.instagram|e }}
</span>
<svg class="external-link" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> <svg class="external-link" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512">
<path fill="currentColor" d="M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z"></path> <path fill="currentColor" d="M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z"></path>
</svg> </svg>
@ -387,12 +395,7 @@
</div> </div>
<div class="contact-content"> <div class="contact-content">
<a href="{{ data.contacts.twitter|e }}"> <a href="{{ data.contacts.twitter|e }}">
<span class="short"> Profil Twitter
{{ data.contacts.twitterLabel|e }}
</span>
<span class="long">
{{ data.contacts.twitter|e }}
</span>
<svg class="external-link" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"> <svg class="external-link" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512">
<path fill="currentColor" d="M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z"></path> <path fill="currentColor" d="M432,320H400a16,16,0,0,0-16,16V448H64V128H208a16,16,0,0,0,16-16V80a16,16,0,0,0-16-16H48A48,48,0,0,0,0,112V464a48,48,0,0,0,48,48H400a48,48,0,0,0,48-48V336A16,16,0,0,0,432,320ZM488,0h-128c-21.37,0-32.05,25.91-17,41l35.73,35.73L135,320.37a24,24,0,0,0,0,34L157.67,377a24,24,0,0,0,34,0L435.28,133.32,471,169c15,15,41,4.5,41-17V24A24,24,0,0,0,488,0Z"></path>
</svg> </svg>