Compare commits

..

3 commits

Author SHA1 Message Date
j
cdeb79cd90 remove old slider code 2025-03-28 10:50:41 +00:00
j
55314b9fd1 add inline gallery, use for gallery details page 2025-03-28 10:48:55 +00:00
j
f3fed29150 use mardown 2025-03-28 10:48:33 +00:00
8 changed files with 140 additions and 1904 deletions

View file

@ -1,170 +0,0 @@
/** VARIABLES
===================================*/
/** RESET AND LAYOUT
===================================*/
.bx-wrapper {
position: relative;
margin-bottom: 60px;
padding: 0;
*zoom: 1;
-ms-touch-action: pan-y;
touch-action: pan-y;
}
.bx-wrapper img {
max-width: 100%;
display: block;
}
.bxslider {
margin: 0;
padding: 0;
}
ul.bxslider {
list-style: none;
}
.bx-viewport {
/*fix other elements on the page moving (on Chrome)*/
-webkit-transform: translatez(0);
}
/** THEME
===================================*/
.bx-wrapper .bx-pager,
.bx-wrapper .bx-controls-auto {
position: absolute;
bottom: -30px;
width: 100%;
}
/* LOADER */
.bx-wrapper .bx-loading {
min-height: 50px;
height: auto;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 2000;
}
/* PAGER */
.bx-wrapper .bx-pager {
text-align: center;
font-size: .85em;
font-family: Arial;
font-weight: bold;
color: #666;
padding-top: 20px;
}
.bx-wrapper .bx-pager.bx-default-pager a {
background: #666;
text-indent: -9999px;
display: block;
width: 10px;
height: 10px;
margin: 0 5px;
outline: 0;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
.bx-wrapper .bx-pager.bx-default-pager a:hover,
.bx-wrapper .bx-pager.bx-default-pager a.active,
.bx-wrapper .bx-pager.bx-default-pager a:focus {
background: #000;
}
.bx-wrapper .bx-pager-item,
.bx-wrapper .bx-controls-auto .bx-controls-auto-item {
display: inline-block;
vertical-align: bottom;
*zoom: 1;
*display: inline;
}
.bx-wrapper .bx-pager-item {
font-size: 0;
line-height: 0;
}
/* DIRECTION CONTROLS (NEXT / PREV) */
.bx-wrapper .bx-prev {
left: 10px;
background: url('controls.png') no-repeat 0 -32px;
}
.bx-wrapper .bx-prev:hover,
.bx-wrapper .bx-prev:focus {
background-position: 0 0;
}
.bx-wrapper .bx-next {
right: 30px;
background: url('controls.png') no-repeat -43px -32px;
}
.bx-wrapper .bx-next:hover,
.bx-wrapper .bx-next:focus {
background-position: -43px 0;
}
.bx-wrapper .bx-controls-direction a {
position: absolute;
top: 50%;
margin-top: -16px;
outline: 0;
width: 32px;
height: 32px;
text-indent: -9999px;
z-index: 9999;
}
.bx-wrapper .bx-controls-direction a.disabled {
display: none;
}
/* AUTO CONTROLS (START / STOP) */
.bx-wrapper .bx-controls-auto {
text-align: center;
}
.bx-wrapper .bx-controls-auto .bx-start {
display: block;
text-indent: -9999px;
width: 10px;
height: 11px;
outline: 0;
background: url('images/controls.png') -86px -11px no-repeat;
margin: 0 3px;
}
.bx-wrapper .bx-controls-auto .bx-start:hover,
.bx-wrapper .bx-controls-auto .bx-start.active,
.bx-wrapper .bx-controls-auto .bx-start:focus {
background-position: -86px 0;
}
.bx-wrapper .bx-controls-auto .bx-stop {
display: block;
text-indent: -9999px;
width: 9px;
height: 11px;
outline: 0;
background: url('images/controls.png') -86px -44px no-repeat;
margin: 0 3px;
}
.bx-wrapper .bx-controls-auto .bx-stop:hover,
.bx-wrapper .bx-controls-auto .bx-stop.active,
.bx-wrapper .bx-controls-auto .bx-stop:focus {
background-position: -86px -33px;
}
/* PAGER WITH AUTO-CONTROLS HYBRID LAYOUT */
.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-pager {
text-align: left;
width: 80%;
}
.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-controls-auto {
right: 0;
width: 35px;
}
/* IMAGE CAPTIONS */
.bx-wrapper .bx-caption {
position: absolute;
bottom: 0;
left: 0;
background: #666;
background: rgba(80, 80, 80, 0.75);
width: 100%;
}
.bx-wrapper .bx-caption span {
color: #fff;
font-family: Arial;
display: block;
font-size: .85em;
padding: 10px;
}

View file

@ -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;
}
}

View file

@ -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">&#10006;</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">&#10006;</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()
}
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1,50 +0,0 @@
var startSlide = 0;
if (document.querySelectorAll('.select-image').length && document.location.hash.length) {
startSlide = parseInt(document.location.hash.slice(1)) - 1
}
function loadSlideshow() {
$('a.original-link').bind('touchstart MSPointerDown pointerdown', function(event) {
event.stopPropagation()
});
$('a.original-link').on({
mousedown: function(event) {
event.stopPropagation()
},
})
slider = $('.slider1').show().bxSlider({
startSlide: startSlide,
preloadImages: 'all',
adaptiveHeight : true,
pager : false,
});
var images = $('.slider1 img'), count = images.length;
images.on({load: function(event) {
setTimeout(function() {
slider.resize()
slider.redrawSlider()
}, 100)
}})
document.querySelectorAll('.select-image').forEach(function(a) {
a.onclick = function(event) {
event.preventDefault();
slider.goToSlide(parseInt(this.dataset.id) - 1)
document.location.hash = '#' + this.dataset.id;
};
});
$(document).keydown(function(e){
if (e.keyCode == 39) // Right arrow
{
slider && slider.goToNextSlide && slider.goToNextSlide();
return false;
}
else if (e.keyCode == 37) // left arrow
{
slider && slider.goToPrevSlide && slider.goToPrevSlide();
return false;
}
});
}
$(document).ready(loadSlideshow);

View file

@ -10,7 +10,6 @@
{% endblock %} {% endblock %}
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans"/> <link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans"/>
<link rel="stylesheet" type="text/css" href="{% static "css/foundation.css" %}?20250201"> <link rel="stylesheet" type="text/css" href="{% static "css/foundation.css" %}?20250201">
<link rel="stylesheet" type="text/css" href="{% static "css/jquery.bxslider.css" %}">
{% compress css file site %} {% compress css file site %}
<link rel="stylesheet" type="text/css" href="{% static "css/main.css" %}"> <link rel="stylesheet" type="text/css" href="{% static "css/main.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "css/app.css" %}"> <link rel="stylesheet" type="text/css" href="{% static "css/app.css" %}">
@ -47,16 +46,12 @@
{% 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 %}
<script src="{% static "js/app.js" %}"></script> <script src="{% static "js/app.js" %}"></script>
<script src="{% static "js/what-input.js" %}"></script> <script src="{% static "js/what-input.js" %}"></script>
<script src="{% static "js/jquery.bxslider.js" %}?2"></script>
<script src="{% static "js/gallery.js" %}"></script> <script src="{% static "js/gallery.js" %}"></script>
<script src="{% static "js/slideshow.js" %}"></script>
{% endcompress %} {% endcompress %}
{% block end %} {% block end %}
{% endblock %} {% endblock %}

View file

@ -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 %}

View file

@ -8,7 +8,7 @@
<div class="medium-9 columns"> <div class="medium-9 columns">
<img src="{{ object.get_display_url }}" alt="{{ object.title }}"> <img src="{{ object.get_display_url }}" alt="{{ object.title }}">
<p> <p>
{{ object.caption|safe }} {{ object.caption_html }}
{% if object.caption %}<br>{%endif%} {% if object.caption %}<br>{%endif%}
{% if request.user.is_staff %}<a href="{{ photo.image.url }}" class="original-link" target="_blank" >Link to original file</a>{% endif %} {% if request.user.is_staff %}<a href="{{ photo.image.url }}" class="original-link" target="_blank" >Link to original file</a>{% endif %}
</p> </p>