added basic details/edit view + streamlined control through gallery...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
a4712a46ec
commit
7436eb2ada
@ -88,10 +88,6 @@ body {
|
||||
color: var(--gallery-text-color);
|
||||
background: var(--gallery-background-color);
|
||||
}
|
||||
.gallery.lightboxed {
|
||||
--base-layer: 100;
|
||||
}
|
||||
|
||||
.gallery .images {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@ -182,9 +178,19 @@ body {
|
||||
|
||||
|
||||
|
||||
/******************************************************* Lightbox ****/
|
||||
/******************************************************* Overlays ****/
|
||||
|
||||
.gallery .lightbox {
|
||||
.gallery.lightboxed,
|
||||
.gallery.detailed {
|
||||
--base-layer: 100;
|
||||
}
|
||||
.gallery.lightboxed .lightbox,
|
||||
.gallery.detailed .details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.gallery .lightbox,
|
||||
.gallery .details {
|
||||
display: none;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
@ -198,9 +204,10 @@ body {
|
||||
color: var(--lightbox-text-color);
|
||||
background: var(--lightbox-background-color);
|
||||
}
|
||||
.gallery.lightboxed .lightbox {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------ Lightbox ---*/
|
||||
|
||||
.gallery .lightbox.show-caption:before {
|
||||
content: attr(caption);
|
||||
position: absolute;
|
||||
@ -223,14 +230,24 @@ body {
|
||||
var(--lightbox-frame)
|
||||
* var(--lightbox-image-margin-top));
|
||||
}
|
||||
/* controls: next/prev... */
|
||||
.gallery .lightbox .buttons {
|
||||
|
||||
|
||||
/*------------------------------------------------------- Details ---*/
|
||||
|
||||
.gallery .details img {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************* Controls ****/
|
||||
|
||||
.gallery .buttons {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.gallery .lightbox .button {
|
||||
.gallery .button {
|
||||
disbplay: inline-block;
|
||||
cursor: pointer;
|
||||
width: var(--lightbox-button-size);
|
||||
@ -240,27 +257,28 @@ body {
|
||||
filter: saturate(0);
|
||||
opacity: 0.1;
|
||||
}
|
||||
.gallery .lightbox .button:hover {
|
||||
.gallery .button:hover {
|
||||
opacity: 1;
|
||||
filter: saturate(1);
|
||||
color: black;
|
||||
}
|
||||
/* controls: close... */
|
||||
.gallery .lightbox .button.close:after {
|
||||
.gallery .button.close:after {
|
||||
content: "✕";
|
||||
color: red;
|
||||
}
|
||||
.gallery .lightbox .button.fullscreen:after {
|
||||
.gallery .button.fullscreen:after {
|
||||
content: "⛶";
|
||||
color: black;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************** Details ****/
|
||||
|
||||
.gallery .details {
|
||||
display: none;
|
||||
.gallery .button.info:after {
|
||||
content: "i";
|
||||
}
|
||||
.gallery .button.prev:after {
|
||||
content: "<";
|
||||
}
|
||||
.gallery .button.next:after {
|
||||
content: ">";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
|
||||
@ -122,6 +122,7 @@ var restoreScroll = function(){
|
||||
<div class="lightbox">
|
||||
<img>
|
||||
<div class="buttons">
|
||||
<div class="button info"></div>
|
||||
<div class="button fullscreen"></div>
|
||||
<div class="button close"></div>
|
||||
</div>
|
||||
@ -130,13 +131,17 @@ var restoreScroll = function(){
|
||||
<div class="details">
|
||||
<img>
|
||||
<div class="caption">
|
||||
CAPTION
|
||||
</div>
|
||||
<div class="tags">
|
||||
TAGS
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="metadata">
|
||||
METADATA
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div class="button fullscreen"></div>
|
||||
<div class="button prev"></div>
|
||||
<div class="button next"></div>
|
||||
<div class="button close"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
190
grid-n-view.js
190
grid-n-view.js
@ -122,29 +122,36 @@ function(elem) {
|
||||
// XXX add home/end, pageup/pagedown...
|
||||
var keyboard = {
|
||||
ArrowLeft: function(){
|
||||
gallery.lightbox.shown ?
|
||||
gallery.lightbox.prev()
|
||||
: gallery.prev() },
|
||||
gallery.prev() },
|
||||
ArrowRight: function(){
|
||||
gallery.lightbox.shown ?
|
||||
gallery.lightbox.next()
|
||||
: gallery.next() },
|
||||
gallery.next() },
|
||||
// NOTE: up/down will not prevent the default scrolling behavior
|
||||
// when at top/bottom of the gallery.
|
||||
ArrowUp: function(evt){
|
||||
gallery.__at_top_row
|
||||
|| evt.preventDefault()
|
||||
;(gallery.dom.classList.contains('lightboxed')
|
||||
|| gallery.dom.classList.contains('detailed'))
|
||||
&& evt.preventDefault()
|
||||
gallery.lightbox.shown
|
||||
|| gallery.details.shown
|
||||
|| gallery.up() },
|
||||
ArrowDown: function(evt){
|
||||
gallery.__at_bottom_row
|
||||
|| evt.preventDefault()
|
||||
;(gallery.dom.classList.contains('lightboxed')
|
||||
|| gallery.dom.classList.contains('detailed'))
|
||||
&& evt.preventDefault()
|
||||
gallery.lightbox.shown
|
||||
|| gallery.details.shown
|
||||
|| gallery.down() },
|
||||
Enter: function(){
|
||||
gallery.lightbox.toggle() },
|
||||
// XXX need a real ui stack -- close top to bottom...
|
||||
Escape: function(evt){
|
||||
gallery.lightbox.shown ?
|
||||
gallery.details.shown ?
|
||||
gallery.details.hide()
|
||||
: gallery.lightbox.shown ?
|
||||
gallery.lightbox.hide()
|
||||
// XXX should we remember which image was current and select
|
||||
// it again when needed???
|
||||
@ -263,6 +270,16 @@ var Gallery = {
|
||||
this)) }
|
||||
delete this.__lightbox
|
||||
return undefined },
|
||||
__details: undefined,
|
||||
get details(){
|
||||
if(this.dom){
|
||||
return this.__details
|
||||
?? (this.__details = { __proto__: Details }
|
||||
.setup(
|
||||
this.dom.querySelector('.details'),
|
||||
this)) }
|
||||
delete this.__details
|
||||
return undefined },
|
||||
|
||||
__at_top_row: undefined,
|
||||
__at_bottom_row: undefined,
|
||||
@ -448,6 +465,7 @@ var Gallery = {
|
||||
images.length-1
|
||||
: 0
|
||||
this.current = images[i]
|
||||
this.update()
|
||||
return this },
|
||||
next: function(images){
|
||||
images ??= this.images
|
||||
@ -460,6 +478,7 @@ var Gallery = {
|
||||
0
|
||||
: images.length-1
|
||||
this.current = images[i]
|
||||
this.update()
|
||||
return this },
|
||||
|
||||
// navigate images visually...
|
||||
@ -546,12 +565,25 @@ var Gallery = {
|
||||
show: function(){
|
||||
this.lightbox.show()
|
||||
return this },
|
||||
showLightbox: function(){
|
||||
this.lightbox.show()
|
||||
return this },
|
||||
showDetails: function(){
|
||||
this.details.show()
|
||||
return this },
|
||||
|
||||
update: function(){
|
||||
__update_grid_size: function(){
|
||||
patchFlexRows(this.images,
|
||||
!this.allow_row_expansion,
|
||||
this.last_row_resize ?? 1.2)
|
||||
return this },
|
||||
update: function(){
|
||||
this.__update_grid_size()
|
||||
this.lightbox.shown
|
||||
&& this.lightbox.update()
|
||||
this.details.shown
|
||||
&& this.details.update()
|
||||
return this },
|
||||
|
||||
// .load(<image>)
|
||||
// .load(<images>)
|
||||
@ -690,7 +722,7 @@ var Gallery = {
|
||||
// handle resizing...
|
||||
new ResizeObserver(
|
||||
function(elems){
|
||||
that.update() })
|
||||
that.__update_grid_size() })
|
||||
.observe(this.dom)
|
||||
|
||||
return this
|
||||
@ -701,16 +733,10 @@ var Gallery = {
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
// XXX ignore click from blur...
|
||||
var Lightbox = {
|
||||
var Overlay = {
|
||||
dom: undefined,
|
||||
gallery: undefined,
|
||||
|
||||
caption_format: '${INDEX} ${CAPTION}',
|
||||
|
||||
navigation_deadzone: 100,
|
||||
caption_hysteresis: 10,
|
||||
cache_count: 1,
|
||||
cls: 'overlay',
|
||||
|
||||
get url(){
|
||||
return this.dom.querySelector('img').src },
|
||||
@ -719,31 +745,34 @@ var Lightbox = {
|
||||
// remove preview dir...
|
||||
.replace(/\/[0-9]+px\//, '/')
|
||||
// cache...
|
||||
this.cache_count != 0
|
||||
this.cache
|
||||
&& this.cache_count != 0
|
||||
&& this.cache() },
|
||||
|
||||
get shown(){
|
||||
return this.gallery.dom.classList.contains('lightboxed') },
|
||||
show: function(url){
|
||||
this.url = url
|
||||
?? (this.gallery.current
|
||||
?? this.gallery.next().current
|
||||
?? {}).src
|
||||
return this.gallery.dom.classList.contains(this.cls) },
|
||||
show: function(){
|
||||
this.update()
|
||||
this.gallery.dom.classList.add('lightboxed')
|
||||
this.gallery.dom.classList.add(this.cls)
|
||||
return this },
|
||||
hide: function(){
|
||||
this.gallery.exit_fullscreen_on_lightbox_close
|
||||
&& document.fullscreenElement
|
||||
&& document.exitFullscreen()
|
||||
this.gallery.dom.classList.remove('lightboxed')
|
||||
this.gallery.dom.classList.remove(this.cls)
|
||||
return this },
|
||||
toggle: function(){
|
||||
return this.shown ?
|
||||
this.hide()
|
||||
: this.show() },
|
||||
|
||||
cache: null,
|
||||
|
||||
update: function(){
|
||||
this.url =
|
||||
(this.gallery.current
|
||||
?? this.gallery.next().current
|
||||
?? {}).src
|
||||
var caption =
|
||||
(this.gallery.current
|
||||
?? this.gallery.next().current
|
||||
@ -754,7 +783,7 @@ var Lightbox = {
|
||||
// set caption...
|
||||
// XXX should these be separate elements???
|
||||
this.dom.setAttribute('caption',
|
||||
this.caption_format
|
||||
(this.caption_format ?? '${CAPTION}')
|
||||
.replace(/\${CAPTION}/, caption)
|
||||
.replace(/\${INDEX}/, index))
|
||||
// set selection...
|
||||
@ -763,12 +792,67 @@ var Lightbox = {
|
||||
: this.dom.classList.remove('marked')
|
||||
return this },
|
||||
|
||||
prev: function(){
|
||||
this.gallery.prev().show()
|
||||
return this },
|
||||
next: function(){
|
||||
this.gallery.next().show()
|
||||
setup: function(dom, gallery){
|
||||
var that = this
|
||||
this.dom = dom
|
||||
this.gallery = gallery
|
||||
|
||||
// controls...
|
||||
this.dom.querySelector('.close')
|
||||
?.addEventListener('click', function(evt){
|
||||
evt.stopPropagation()
|
||||
that.hide() })
|
||||
this.dom.querySelector('.fullscreen')
|
||||
?.addEventListener('click', function(evt){
|
||||
evt.stopPropagation()
|
||||
document.fullscreenElement ?
|
||||
document.exitFullscreen()
|
||||
: that.dom.requestFullscreen() })
|
||||
this.dom.querySelector('.info')
|
||||
?.addEventListener('click', function(evt){
|
||||
evt.stopPropagation()
|
||||
that.gallery.showDetails() })
|
||||
this.dom.querySelector('.prev')
|
||||
?.addEventListener('click', function(evt){
|
||||
evt.stopPropagation()
|
||||
that.gallery.prev() })
|
||||
this.dom.querySelector('.next')
|
||||
?.addEventListener('click', function(evt){
|
||||
evt.stopPropagation()
|
||||
that.gallery.next() })
|
||||
// stop body from scrolling...
|
||||
var stop = function(evt){
|
||||
evt.stopPropagation()
|
||||
evt.preventDefault()
|
||||
return false }
|
||||
this.dom.addEventListener('touchmove', stop)
|
||||
this.dom.addEventListener('mousewheel', stop)
|
||||
this.dom.addEventListener('wheel', stop)
|
||||
this.dom.addEventListener('scroll', stop)
|
||||
// drag...
|
||||
this.dom
|
||||
.addEventListener('dragover', function(evt){
|
||||
that.gallery.dom.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest',
|
||||
})
|
||||
that.hide() })
|
||||
return this },
|
||||
}
|
||||
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
var Lightbox = {
|
||||
__proto__: Overlay,
|
||||
|
||||
cls: 'lightboxed',
|
||||
|
||||
caption_format: '${INDEX} ${CAPTION}',
|
||||
|
||||
navigation_deadzone: 100,
|
||||
caption_hysteresis: 10,
|
||||
cache_count: 1,
|
||||
|
||||
__cache: undefined,
|
||||
cache: function(){
|
||||
@ -795,28 +879,10 @@ var Lightbox = {
|
||||
|
||||
setup: function(dom, gallery){
|
||||
var that = this
|
||||
this.dom = dom
|
||||
this.gallery = gallery
|
||||
// controls...
|
||||
this.dom.querySelector('.close')
|
||||
.addEventListener('click', function(evt){
|
||||
evt.stopPropagation()
|
||||
that.hide() })
|
||||
this.dom.querySelector('.fullscreen')
|
||||
.addEventListener('click', function(evt){
|
||||
evt.stopPropagation()
|
||||
document.fullscreenElement ?
|
||||
document.exitFullscreen()
|
||||
: that.dom.requestFullscreen() })
|
||||
// drag...
|
||||
this.dom
|
||||
.addEventListener('dragover', function(evt){
|
||||
that.gallery.dom.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest',
|
||||
})
|
||||
that.hide() })
|
||||
// click...
|
||||
|
||||
Overlay.setup.call(this, ...arguments)
|
||||
|
||||
// click zones...
|
||||
var deadzone = this.navigation_deadzone ?? 100
|
||||
this.dom
|
||||
.addEventListener('click', function(evt){
|
||||
@ -824,10 +890,10 @@ var Lightbox = {
|
||||
// click left/right side of view...
|
||||
// NOTE: this is vewport-relative...
|
||||
evt.clientX < that.dom.offsetWidth / 2 - deadzone/2
|
||||
&& that.prev()
|
||||
&& that.gallery.prev()
|
||||
evt.clientX > that.dom.offsetWidth / 2 + deadzone/2
|
||||
&& that.next() })
|
||||
// mousemove...
|
||||
&& that.gallery.next() })
|
||||
// hover zones...
|
||||
var hysteresis = this.caption_hysteresis ?? 10
|
||||
this.dom
|
||||
.addEventListener('mousemove', function(evt){
|
||||
@ -856,6 +922,16 @@ var Lightbox = {
|
||||
}
|
||||
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
var Details = {
|
||||
__proto__: Overlay,
|
||||
|
||||
cls: 'detailed',
|
||||
|
||||
// XXX
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user