add inline gallery, use for gallery details page
This commit is contained in:
parent
f3fed29150
commit
55314b9fd1
4 changed files with 139 additions and 69 deletions
|
@ -1,4 +1,4 @@
|
||||||
.gallery-dialog {
|
.gallery-dialog, .gallery-main-stage {
|
||||||
&:open {
|
&:open {
|
||||||
background: #282828;
|
background: #282828;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -52,9 +52,6 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
}
|
}
|
||||||
.thumbnail.active {
|
|
||||||
border-color: blue;
|
|
||||||
}
|
|
||||||
.nav-btn {
|
.nav-btn {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
@ -122,3 +119,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gallery-main-stage {
|
||||||
|
.photo-container .image {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.download {
|
||||||
|
right: 4px
|
||||||
|
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 39.9375em) {
|
||||||
|
.download {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-dialog, .inline-gallery {
|
||||||
|
.thumbnail {
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
}
|
||||||
|
.thumbnail.active {
|
||||||
|
cursor: initial;
|
||||||
|
border-color: #1779ba;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
|
function isNumber(x) {
|
||||||
|
return parseFloat(x) == x
|
||||||
|
};
|
||||||
|
|
||||||
function parseGalleryHash() {
|
function parseGalleryHash() {
|
||||||
let parts = document.location.hash.slice(1).split('/')
|
let parts = document.location.hash.slice(1).split('/')
|
||||||
if (parts[0] == 'g') {
|
if (parts.lengh == 1 && isNumber(parts[0])) {
|
||||||
return {
|
return {
|
||||||
"gallery": parseInt(parts[1], 10),
|
'gallery': 'inline',
|
||||||
"image": parseInt(parts[2], 10),
|
"image": parseInt(parts[0], 10) - 1,
|
||||||
|
}
|
||||||
|
} else if (parts.length == 2 && isNumber(parts[0]) && isNumber(parts[1])) {
|
||||||
|
return {
|
||||||
|
"gallery": parseInt(parts[0], 10) - 1,
|
||||||
|
"image": parseInt(parts[1], 10) - 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
|
@ -11,7 +20,7 @@ function parseGalleryHash() {
|
||||||
|
|
||||||
function loadGalleries() {
|
function loadGalleries() {
|
||||||
let current = parseGalleryHash()
|
let current = parseGalleryHash()
|
||||||
let galleryIdx = 1
|
let galleryIdx = 0
|
||||||
document.querySelectorAll('.gallery').forEach(gallery => {
|
document.querySelectorAll('.gallery').forEach(gallery => {
|
||||||
var photos = [], dialog
|
var photos = [], dialog
|
||||||
gallery.querySelectorAll(".photo").forEach(img => {
|
gallery.querySelectorAll(".photo").forEach(img => {
|
||||||
|
@ -35,49 +44,77 @@ function loadGalleries() {
|
||||||
}
|
}
|
||||||
galleryIdx += 1
|
galleryIdx += 1
|
||||||
})
|
})
|
||||||
|
document.querySelectorAll('.inline-gallery').forEach(gallery => {
|
||||||
|
var photos = [], stage
|
||||||
|
gallery.querySelectorAll(".photo").forEach(img => {
|
||||||
|
const src = img.src.replace('_thumbnail', '_display')
|
||||||
|
let photo = {
|
||||||
|
src: src,
|
||||||
|
caption: img.dataset.caption,
|
||||||
|
orig: img.dataset.orig
|
||||||
|
}
|
||||||
|
photos.push(photo)
|
||||||
|
img.parentElement.addEventListener("click", event => {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
stage.open(src)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const main = document.querySelector('.gallery-main-stage')
|
||||||
|
stage = loadGallery(photos, 'inline', main, gallery)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadGallery(images, idx) {
|
function loadGallery(images, idx, main, thumbnails) {
|
||||||
var gallery = document.createElement("dialog")
|
let gallery;
|
||||||
gallery.classList.add("gallery-dialog")
|
|
||||||
gallery.innerHTML = `
|
|
||||||
<div class="photo-container">
|
|
||||||
<div class="image">
|
|
||||||
<img class="main-image" src="" alt="">
|
|
||||||
</div>
|
|
||||||
<button class="prev nav-btn">❮ Prev</button>
|
|
||||||
<button class="next nav-btn">Next ❯</button>
|
|
||||||
</div>
|
|
||||||
<button class="close">✖</button>
|
|
||||||
<a class="download disabled" target="_blank" download title="download original">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 304 384"><path fill="currentColor" d="M299 128L149 277L0 128h85V0h128v128h86zM0 320h299v43H0v-43z"/></svg>
|
|
||||||
</a>
|
|
||||||
<div class="caption"></div>
|
|
||||||
<div class="thumbnails"></div>
|
|
||||||
`
|
|
||||||
|
|
||||||
gallery.addEventListener("click", event => {
|
if (idx == 'inline') {
|
||||||
if (event.target.className == "close") {
|
gallery = main
|
||||||
document.location.hash = ''
|
} else {
|
||||||
gallery.close();
|
gallery = document.createElement("dialog")
|
||||||
return
|
gallery.classList.add("gallery-dialog")
|
||||||
}
|
gallery.innerHTML = `
|
||||||
var rect = gallery.getBoundingClientRect();
|
<div class="photo-container">
|
||||||
var isInDialog = (rect.top <= event.clientY && event.clientY <= rect.top + rect.height &&
|
<div class="image">
|
||||||
rect.left <= event.clientX && event.clientX <= rect.left + rect.width);
|
<img class="main-image" src="" alt="">
|
||||||
if (!isInDialog) {
|
</div>
|
||||||
document.location.hash = ''
|
<button class="prev nav-btn">❮ Prev</button>
|
||||||
gallery.close();
|
<button class="next nav-btn">Next ❯</button>
|
||||||
}
|
</div>
|
||||||
})
|
<button class="close">✖</button>
|
||||||
|
<a class="download disabled" target="_blank" download title="download original">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 304 384"><path fill="currentColor" d="M299 128L149 277L0 128h85V0h128v128h86zM0 320h299v43H0v-43z"/></svg>
|
||||||
|
</a>
|
||||||
|
<div class="caption"></div>
|
||||||
|
<div class="thumbnails"></div>
|
||||||
|
`
|
||||||
|
|
||||||
|
gallery.addEventListener("click", event => {
|
||||||
|
if (event.target.className == "close") {
|
||||||
|
document.location.hash = ''
|
||||||
|
gallery.close();
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var rect = gallery.getBoundingClientRect();
|
||||||
|
var isInDialog = (rect.top <= event.clientY && event.clientY <= rect.top + rect.height &&
|
||||||
|
rect.left <= event.clientX && event.clientX <= rect.left + rect.width);
|
||||||
|
if (!isInDialog) {
|
||||||
|
document.location.hash = ''
|
||||||
|
gallery.close();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
let currentIndex = 0;
|
let currentIndex = 0;
|
||||||
|
|
||||||
const mainImage = gallery.querySelector(".main-image");
|
const mainImage = gallery.querySelector(".main-image");
|
||||||
const caption = gallery.querySelector(".caption");
|
const caption = gallery.querySelector(".caption");
|
||||||
const prevBtn = gallery.querySelector(".prev.nav-btn");
|
const prevBtn = gallery.querySelector(".prev.nav-btn");
|
||||||
const nextBtn = gallery.querySelector(".next.nav-btn");
|
const nextBtn = gallery.querySelector(".next.nav-btn");
|
||||||
const thumbnailsContainer = gallery.querySelector(".thumbnails");
|
|
||||||
const download = gallery.querySelector(".download");
|
const download = gallery.querySelector(".download");
|
||||||
|
let thumbnailsContainer
|
||||||
|
if (idx != 'inline') {
|
||||||
|
thumbnailsContainer = gallery.querySelector(".thumbnails");
|
||||||
|
}
|
||||||
|
|
||||||
gallery.addEventListener("keydown", event => {
|
gallery.addEventListener("keydown", event => {
|
||||||
if (event.keyCode == 39) {
|
if (event.keyCode == 39) {
|
||||||
|
@ -97,9 +134,15 @@ function loadGallery(images, idx) {
|
||||||
mainImage.src = images[index].src;
|
mainImage.src = images[index].src;
|
||||||
}, 0)
|
}, 0)
|
||||||
caption.innerHTML = images[index].caption;
|
caption.innerHTML = images[index].caption;
|
||||||
gallery.querySelectorAll(".thumbnail").forEach((thumb, i) => {
|
if (idx == 'inline') {
|
||||||
thumb.classList.toggle("active", i === index);
|
thumbnails.querySelectorAll(".thumbnail").forEach((thumb, i) => {
|
||||||
});
|
thumb.classList.toggle("active", i === index);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
gallery.querySelectorAll(".thumbnail").forEach((thumb, i) => {
|
||||||
|
thumb.classList.toggle("active", i === index);
|
||||||
|
});
|
||||||
|
}
|
||||||
if (images[index].orig) {
|
if (images[index].orig) {
|
||||||
download.href = images[index].orig
|
download.href = images[index].orig
|
||||||
download.classList.remove('disabled')
|
download.classList.remove('disabled')
|
||||||
|
@ -109,7 +152,11 @@ function loadGallery(images, idx) {
|
||||||
}
|
}
|
||||||
prevBtn.disabled = index === 0;
|
prevBtn.disabled = index === 0;
|
||||||
nextBtn.disabled = index === images.length - 1;
|
nextBtn.disabled = index === images.length - 1;
|
||||||
document.location.hash = `#g/${idx}/${index}`
|
if (idx == 'inline') {
|
||||||
|
document.location.hash = `#${index + 1}`
|
||||||
|
} else {
|
||||||
|
document.location.hash = `#${idx + 1}/${index + 1}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createThumbnails() {
|
function createThumbnails() {
|
||||||
|
@ -144,20 +191,23 @@ function loadGallery(images, idx) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
createThumbnails();
|
idx != 'inline' && createThumbnails();
|
||||||
updateGallery(currentIndex);
|
updateGallery(currentIndex);
|
||||||
|
|
||||||
const imagesIndex = images.map(img => img.src);
|
const imagesIndex = images.map(img => img.src);
|
||||||
return {
|
return {
|
||||||
element: gallery,
|
element: gallery,
|
||||||
open: function(src, idx=-1) {
|
open: function(src, newIdx=-1) {
|
||||||
if (idx != -1) {
|
if (newIdx != -1) {
|
||||||
currentIndex = idx
|
currentIndex = newIdx
|
||||||
} else {
|
} else {
|
||||||
currentIndex = imagesIndex.indexOf(src)
|
currentIndex = imagesIndex.indexOf(src)
|
||||||
}
|
}
|
||||||
updateGallery(currentIndex)
|
updateGallery(currentIndex)
|
||||||
showGallery()
|
console.log("!WTF", idx)
|
||||||
|
if (idx != 'inline') {
|
||||||
|
showGallery()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,6 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
{}
|
|
||||||
<script src="{% static "js/jquery.js" %}"></script>
|
<script src="{% static "js/jquery.js" %}"></script>
|
||||||
<script src="{% static "js/foundation.js" %}"></script>
|
<script src="{% static "js/foundation.js" %}"></script>
|
||||||
{% compress js file base %}
|
{% compress js file base %}
|
||||||
|
|
|
@ -10,33 +10,34 @@
|
||||||
<h6 class="page-header"><a href="{{ gallery.content.all.0.get_absolute_url }}">Back to {{ gallery.content.all.0.title }}</a></h6>
|
<h6 class="page-header"><a href="{{ gallery.content.all.0.get_absolute_url }}">Back to {{ gallery.content.all.0.title }}</a></h6>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<h5>{{ gallery.title }}</h5>
|
<h5>{{ gallery.title }}</h5>
|
||||||
<ul class="slider1">
|
{% with gallery.public.0 as photo %}
|
||||||
{% for photo in gallery.public %}
|
<div class="gallery-main-stage">
|
||||||
<li id="slide-{{photo.slug}}">
|
<div class="photo-container">
|
||||||
<img src="{{ photo.get_display_url }}" alt="{{ photo.title }}" loading="lazy">
|
<div class="image">
|
||||||
<p>
|
<img src="{{ photo.get_display_url }}" alt="{{ photo.title }}" class="main-image" alt="{{ photo.title }}">
|
||||||
{{ photo.caption|safe }}
|
</div>
|
||||||
{% if photo.caption %}<br>{%endif%}
|
<button class="prev nav-btn">❮ Prev</button>
|
||||||
{% if request.user.is_staff %}<a href="{{ photo.image.url }}" class="original-link" target="_blank" >Link to original file</a>{% endif %}
|
<button class="next nav-btn">Next ❯</button>
|
||||||
</p>
|
<a class="download disabled" target="_blank" download title="download original">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 304 384"><path fill="currentColor" d="M299 128L149 277L0 128h85V0h128v128h86zM0 320h299v43H0v-43z"/></svg>
|
||||||
</li>
|
</a>
|
||||||
{% endfor %}
|
</div>
|
||||||
</ul>
|
<div class="caption">{{ photo.caption_html }}</div>
|
||||||
|
</div>
|
||||||
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
<div class="medium-3 columns">
|
<div class="medium-3 columns">
|
||||||
<br>
|
<br>
|
||||||
<p>{% trans "Other photos" %}:</p>
|
<p>{% trans "Other photos" %}:</p>
|
||||||
<div>
|
<div class="inline-gallery">
|
||||||
{% for photo in gallery.public %}
|
{% for photo in gallery.public %}
|
||||||
<div style="float: left; padding: 4px">
|
<div style="float: left; padding: 4px">
|
||||||
<a href="{{ photo.get_absolute_url }}" class="select-image" data-id="{{forloop.counter}}">
|
<a href="{{ gallery.get_absolute_url }}#{{forloop.counter}}">
|
||||||
<img src="{{ photo.get_thumbnail_url }}" class="thumbnail" alt="{{ photo.title }}">
|
<img src="{{ photo.get_thumbnail_url }}" class="thumbnail photo" alt="{{ photo.title }}" data-caption="{{ photo.caption_html }}"{% if request.user.is_staff %} data-orig="{{ photo.image.url }}"{% endif %}>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Loading…
Add table
Reference in a new issue