added removal queue API + cleanup and notes...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2023-08-13 00:23:13 +03:00
parent 5ffdaeb100
commit 804bceee46
3 changed files with 149 additions and 33 deletions

View File

@ -10,8 +10,8 @@
:root {
/* dimensions */
--gallery-image-margin: 0;
--gallery-current-image-border: 0.7em;
--gallery-padding: 3em;
--gallery-current-image-border: 0.7rem;
--gallery-padding: 3rem;
--gallery-padding-horizontal: var(--gallery-padding);
--gallery-padding-vertical: var(--gallery-current-image-border);
--gallery-padding-top: var(--gallery-padding-vertical);
@ -19,8 +19,8 @@
--gallery-padding-left: var(--gallery-padding-horizontal);
--gallery-padding-right: var(--gallery-padding-horizontal);
--gallery-image-scroll-margin: calc(2 * var(--gallery-current-image-border));
--gallery-scrollbar-width: 0.5em;
--gallery-empty-height: 20em;
--gallery-scrollbar-width: 0.5rem;
--gallery-empty-height: 20rem;
--lightbox-frame: 5vmin;
--lightbox-image-margin-top: 0.75;
@ -96,19 +96,33 @@ body {
align-content: flex-start;
flex-flow: row wrap;
}
/* empty... */
.gallery .images:empty {
height: var(--gallery-empty-height);
border: dashed 1px black;
}
.gallery .images:empty:after {
content: "Empty...";
.gallery .images:empty:after,
.gallery .images:empty:before {
position: absolute;
width: 100%;
left: 0;
top: 0;
padding: calc((var(--gallery-empty-height) - 1em) / 2) 0;
line-height: var(--gallery-empty-height);
text-align: center;
opacity: 0.6;
}
.gallery .images:empty:before {
content: "Empty";
}
.gallery .images:empty:after {
content: "(drag new images here)";
font-size: small;
margin-top: 1.1em;
opacity: 0.4;
}
/* image... */
.gallery .images img {
height: 300px;
width: auto;

View File

@ -112,7 +112,7 @@ var restoreScroll = function(){
</pre>
<pre>
Controls:
Keyboard controls:
Left / Reight - Previos / next image
Up / Down - Image above / below
Space - Mark image (also shift-click)
@ -127,10 +127,32 @@ Controls:
NOTE: if the grid behaves in an odd way on resize tweak PATCH_MARGIN value,
though this sould not be necessary.
(optimal range &gt;1 and &lt;3)
NOTE: the "basic actions" below are to be moved to the toolbar...
For more info see: <a href="./README.md">README.md</a>
</pre>
<hr>
Basic actions:<br>
<a href="javascript:gallery.toggleMark()">toggle mark current (space)</a> |
<a href="javascript:gallery.markAll()">mark all (ctrl-a)</a> |
<a href="javascript:gallery.unmarkAll()">unmark all (ctrl-d)</a> |
<a href="javascript:gallery.markInverse()">reverse mark (ctrl-i)</a> |
<a href="javascript:gallery.remove('marked')">remove marked</a>
<br>
<br>
<a href="javascript:gallery.toggleQueueRemoval()">toggle removal</a> |
<a href="javascript:gallery.queueRemoval('marked')">queue marked removal</a> |
<a href="javascript:gallery.unqueueRemoval('marked')">unqueue marked removal</a> |
<a href="javascript:gallery.toggleQueueRemoval('marked')">toggle marked removal</a> |
<a href="javascript:gallery.removeQueued()">remove queued</a>
<br>
<br>
<a href="javascript:gallery.clear()">clear</a>
<hr>
<div class="gallery">
<!-- gallery: content -->
<div class="images">

View File

@ -15,6 +15,9 @@
var PATCH_MARGIN = 2
// a timeout to let the resize settle before we handle dragover...
// XXX this is too long -- we can pickup and drag an image within this
// timeout...
// need to make it more specific (handle only vertical drag???)
var RESIZE_SETTLE_TIMEOUT = 16
@ -178,19 +181,18 @@ var keyboard = {
Delete: function(evt){
// remove...
if(evt.shiftKey){
// XXX focus crrect image...
to_remove = [...gallery.dom.querySelectorAll('.images img.to-remove')]
var to_remove = gallery.toBeRemoved
// remove marked...
if(to_remove.length > 0){
gallery.remove(...to_remove)
gallery.removeQueued()
// remove current...
} else if(gallery.current){
var to_remove = gallery.current
to_remove = gallery.current
if(gallery.marked.includes(to_remove)){
gallery.remove(...gallery.marked)
} else {
// move focus...
gallery.next()
// XXX this is a bit crude...
gallery.current === to_remove
&& gallery.prev()
gallery.remove(to_remove) } }
@ -199,14 +201,10 @@ var keyboard = {
var cur = gallery.current
// toggle marked...
if(gallery.marked.includes(cur)){
var toggle_remove = !cur.classList.contains('to-remove')
for(var img of gallery.marked){
toggle_remove ?
img.classList.add('to-remove')
: img.classList.remove('to-remove') }
gallery.toggleQueueRemoval('marked')
// toggle current...
} else {
gallery.current.classList.toggle('to-remove') } } },
gallery.toggleQueueRemoval() } } },
// selection...
' ': function(evt){
gallery.current
@ -216,7 +214,7 @@ var keyboard = {
'a': function(evt){
evt.preventDefault()
if(evt.ctrlKey){
gallery.selectAll() } },
gallery.markAll() } },
'd': function(evt){
evt.preventDefault()
if(evt.ctrlKey){
@ -501,6 +499,67 @@ var Gallery = {
: i
var target = row[i] }
return target },
//
// .getImages()
// -> []
//
// .getImages('*')
// .getImages('all')
// -> <all-images>
//
// .getImages('marked')
// -> <marked-images>
//
// .getImages(<img>, ..)
// .getImages([<img>, ..])
// -> <images>
//
// .getImages('sorted', ..)
// .getImages(.., 'sorted')
// -> <sorted-images>
//
// <img> ::=
// ImageElement
// | <index>
// | 'current'
//
getImages: function(...images){
var that = this
var sorted =
images.at(-1) == 'sorted' ?
!!images.pop()
: images[0] == 'sorted' ?
!!images.shift()
: false
images = images.flat()
if(images.includes('all')
|| images.includes('*')){
return this.images }
images = [...new Set(images
.map(function(img){
return ((typeof(img) == 'string'
&& img.trim() == '') ?
[]
: !isNaN(img*1) ?
that.images.at(img*1)
: img == 'marked' ?
that.marked
: img == 'current' ?
that.current
: typeof(img) == 'string' ?
[]
: img)
?? [] })
.flat())]
if(sorted){
var order = new Map(
Object.entries(this.images)
.map(function(e){
return e.reverse() }))
images
.sort(function(a, b){
return order.get(a) - order.get(b) }) }
return images },
// XXX cache image list???
prev: function(images){
@ -598,7 +657,7 @@ var Gallery = {
img?.classList.toggle('marked')
this.updateMarkers()
return this },
selectAll: function(){
markAll: function(){
for(var img of this.images){
img.classList.add('marked') }
return this.updateMarkers() },
@ -726,15 +785,7 @@ var Gallery = {
// XXX do we handle previews here???
json: function(images=undefined){
var that = this
images =
(images == 'all' || images == '*') ?
this.images
: images == 'marked' ?
this.marked
: !images ?
this.images
: images
return images
return this.getImages(images ?? this.images)
.map(function(img, i){
var res = { url: img.src }
for(var key of that.__image_attributes__ ?? []){
@ -752,13 +803,42 @@ var Gallery = {
// XXX
},
// removal queue...
get toBeRemoved(){
return [...gallery.dom.querySelectorAll('.images img.to-remove')] },
set toBeRemoved(lst){
this.queueRemoval(lst) },
queueRemoval: function(...images){
images = images.length == 0 ?
['current']
: images
for(var img of this.getImages(...images)){
img.classList.add('to-remove') }
return this },
unqueueRemoval: function(...images){
images = images.length == 0 ?
['current']
: images
for(var img of this.getImages(...images)){
img.classList.remove('to-remove') }
return this },
toggleQueueRemoval: function(...images){
images = images.length == 0 ?
['current']
: images
for(var img of this.getImages(...images)){
img.classList.toggle('to-remove') }
return this },
removeQueued: function(){
return this.remove(...this.toBeRemoved) },
remove: function(...images){
if(images.includes('all')){
if(images.includes('all')
|| images.includes('*')){
return this.clear() }
// NOTE: we need to remove images from the end so as not to be
// affected by shifed indexes...
images
.sort()
images = this.getImages('sorted', ...images)
.reverse()
for(var img of images){
typeof(img) == 'number' ?